comctl32/tests: Make test_combo_WS_VSCROLL() static.
[wine.git] / dlls / strmbase / pospass.c
blob45eb23482ded48c4164f0f5016dfd027ee612cb4
1 /*
2 * Filter Seeking and Control Interfaces
4 * Copyright 2003 Robert Shearman
5 * Copyright 2012 Aric Stewart, CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 /* FIXME: critical sections */
23 #define COBJMACROS
25 #include "dshow.h"
26 #include "uuids.h"
28 #include "wine/debug.h"
29 #include "wine/strmbase.h"
31 #include <assert.h>
33 WINE_DEFAULT_DEBUG_CHANNEL(strmbase);
35 static const IMediaSeekingVtbl IMediaSeekingPassThru_Vtbl;
36 static const IMediaPositionVtbl IMediaPositionPassThru_Vtbl;
38 typedef struct PassThruImpl {
39 IUnknown IUnknown_inner;
40 ISeekingPassThru ISeekingPassThru_iface;
41 IMediaSeeking IMediaSeeking_iface;
42 IMediaPosition IMediaPosition_iface;
43 BaseDispatch baseDispatch;
45 LONG ref;
46 IUnknown * outer_unk;
47 IPin * pin;
48 BOOL bUnkOuterValid;
49 BOOL bAggregatable;
50 BOOL renderer;
51 CRITICAL_SECTION time_cs;
52 BOOL timevalid;
53 REFERENCE_TIME time_earliest;
54 } PassThruImpl;
56 static inline PassThruImpl *impl_from_IUnknown_inner(IUnknown *iface)
58 return CONTAINING_RECORD(iface, PassThruImpl, IUnknown_inner);
61 static inline PassThruImpl *impl_from_ISeekingPassThru(ISeekingPassThru *iface)
63 return CONTAINING_RECORD(iface, PassThruImpl, ISeekingPassThru_iface);
66 static inline PassThruImpl *impl_from_IMediaSeeking(IMediaSeeking *iface)
68 return CONTAINING_RECORD(iface, PassThruImpl, IMediaSeeking_iface);
71 static inline PassThruImpl *impl_from_IMediaPosition(IMediaPosition *iface)
73 return CONTAINING_RECORD(iface, PassThruImpl, IMediaPosition_iface);
76 static HRESULT WINAPI SeekInner_QueryInterface(IUnknown * iface,
77 REFIID riid,
78 LPVOID *ppvObj) {
79 PassThruImpl *This = impl_from_IUnknown_inner(iface);
80 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObj);
82 if (This->bAggregatable)
83 This->bUnkOuterValid = TRUE;
85 if (IsEqualGUID(&IID_IUnknown, riid))
87 *ppvObj = &(This->IUnknown_inner);
88 TRACE(" returning IUnknown interface (%p)\n", *ppvObj);
89 } else if (IsEqualGUID(&IID_ISeekingPassThru, riid)) {
90 *ppvObj = &(This->ISeekingPassThru_iface);
91 TRACE(" returning ISeekingPassThru interface (%p)\n", *ppvObj);
92 } else if (IsEqualGUID(&IID_IMediaSeeking, riid)) {
93 *ppvObj = &(This->IMediaSeeking_iface);
94 TRACE(" returning IMediaSeeking interface (%p)\n", *ppvObj);
95 } else if (IsEqualGUID(&IID_IMediaPosition, riid)) {
96 *ppvObj = &(This->IMediaPosition_iface);
97 TRACE(" returning IMediaPosition interface (%p)\n", *ppvObj);
98 } else {
99 *ppvObj = NULL;
100 FIXME("unknown interface %s\n", debugstr_guid(riid));
101 return E_NOINTERFACE;
104 IUnknown_AddRef((IUnknown *)(*ppvObj));
105 return S_OK;
108 static ULONG WINAPI SeekInner_AddRef(IUnknown * iface) {
109 PassThruImpl *This = impl_from_IUnknown_inner(iface);
110 ULONG ref = InterlockedIncrement(&This->ref);
112 TRACE("(%p)->(): new ref = %d\n", This, ref);
114 return ref;
117 static ULONG WINAPI SeekInner_Release(IUnknown * iface) {
118 PassThruImpl *This = impl_from_IUnknown_inner(iface);
119 ULONG ref = InterlockedDecrement(&This->ref);
121 TRACE("(%p)->(): new ref = %d\n", This, ref);
123 if (ref == 0)
125 BaseDispatch_Destroy(&This->baseDispatch);
126 This->time_cs.DebugInfo->Spare[0] = 0;
127 DeleteCriticalSection(&This->time_cs);
128 CoTaskMemFree(This);
130 return ref;
133 static const IUnknownVtbl IInner_VTable =
135 SeekInner_QueryInterface,
136 SeekInner_AddRef,
137 SeekInner_Release
140 /* Generic functions for aggregation */
141 static HRESULT SeekOuter_QueryInterface(PassThruImpl *This, REFIID riid, LPVOID *ppv)
143 if (This->bAggregatable)
144 This->bUnkOuterValid = TRUE;
146 if (This->outer_unk)
148 if (This->bAggregatable)
149 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
151 if (IsEqualIID(riid, &IID_IUnknown))
153 HRESULT hr;
155 IUnknown_AddRef(&This->IUnknown_inner);
156 hr = IUnknown_QueryInterface(&This->IUnknown_inner, riid, ppv);
157 IUnknown_Release(&This->IUnknown_inner);
158 This->bAggregatable = TRUE;
159 return hr;
162 *ppv = NULL;
163 return E_NOINTERFACE;
166 return IUnknown_QueryInterface(&This->IUnknown_inner, riid, ppv);
169 static ULONG SeekOuter_AddRef(PassThruImpl *This)
171 if (This->outer_unk && This->bUnkOuterValid)
172 return IUnknown_AddRef(This->outer_unk);
173 return IUnknown_AddRef(&This->IUnknown_inner);
176 static ULONG SeekOuter_Release(PassThruImpl *This)
178 if (This->outer_unk && This->bUnkOuterValid)
179 return IUnknown_Release(This->outer_unk);
180 return IUnknown_Release(&This->IUnknown_inner);
183 static HRESULT WINAPI SeekingPassThru_QueryInterface(ISeekingPassThru *iface, REFIID riid, LPVOID *ppvObj)
185 PassThruImpl *This = impl_from_ISeekingPassThru(iface);
187 TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj);
189 return SeekOuter_QueryInterface(This, riid, ppvObj);
192 static ULONG WINAPI SeekingPassThru_AddRef(ISeekingPassThru *iface)
194 PassThruImpl *This = impl_from_ISeekingPassThru(iface);
196 TRACE("(%p/%p)->()\n", This, iface);
198 return SeekOuter_AddRef(This);
201 static ULONG WINAPI SeekingPassThru_Release(ISeekingPassThru *iface)
203 PassThruImpl *This = impl_from_ISeekingPassThru(iface);
205 TRACE("(%p/%p)->()\n", This, iface);
207 return SeekOuter_Release(This);
210 static HRESULT WINAPI SeekingPassThru_Init(ISeekingPassThru *iface, BOOL renderer, IPin *pin)
212 PassThruImpl *This = impl_from_ISeekingPassThru(iface);
214 TRACE("(%p/%p)->(%d, %p)\n", This, iface, renderer, pin);
216 if (This->pin)
217 FIXME("Re-initializing?\n");
219 This->renderer = renderer;
220 This->pin = pin;
222 return S_OK;
225 static const ISeekingPassThruVtbl ISeekingPassThru_Vtbl =
227 SeekingPassThru_QueryInterface,
228 SeekingPassThru_AddRef,
229 SeekingPassThru_Release,
230 SeekingPassThru_Init
233 HRESULT WINAPI CreatePosPassThru(IUnknown* pUnkOuter, BOOL bRenderer, IPin *pPin, IUnknown **ppPassThru)
235 HRESULT hr;
236 ISeekingPassThru *passthru;
238 hr = CoCreateInstance(&CLSID_SeekingPassThru, pUnkOuter, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void**)ppPassThru);
239 if (FAILED(hr))
240 return hr;
242 IUnknown_QueryInterface(*ppPassThru, &IID_ISeekingPassThru, (void**)&passthru);
243 hr = ISeekingPassThru_Init(passthru, bRenderer, pPin);
244 ISeekingPassThru_Release(passthru);
246 return hr;
249 HRESULT WINAPI PosPassThru_Construct(IUnknown *pUnkOuter, LPVOID *ppPassThru)
251 PassThruImpl *fimpl;
253 TRACE("(%p,%p)\n", pUnkOuter, ppPassThru);
255 *ppPassThru = fimpl = CoTaskMemAlloc(sizeof(*fimpl));
256 if (!fimpl)
257 return E_OUTOFMEMORY;
259 fimpl->outer_unk = pUnkOuter;
260 fimpl->bUnkOuterValid = FALSE;
261 fimpl->bAggregatable = FALSE;
262 fimpl->IUnknown_inner.lpVtbl = &IInner_VTable;
263 fimpl->ISeekingPassThru_iface.lpVtbl = &ISeekingPassThru_Vtbl;
264 fimpl->IMediaSeeking_iface.lpVtbl = &IMediaSeekingPassThru_Vtbl;
265 fimpl->IMediaPosition_iface.lpVtbl = &IMediaPositionPassThru_Vtbl;
266 fimpl->ref = 1;
267 fimpl->pin = NULL;
268 fimpl->timevalid = FALSE;
269 InitializeCriticalSection(&fimpl->time_cs);
270 fimpl->time_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": PassThruImpl.time_cs");
271 BaseDispatch_Init(&fimpl->baseDispatch, &IID_IMediaPosition);
272 return S_OK;
275 static HRESULT WINAPI MediaSeekingPassThru_QueryInterface(IMediaSeeking *iface, REFIID riid, LPVOID *ppvObj)
277 PassThruImpl *This = impl_from_IMediaSeeking(iface);
279 TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj);
281 return SeekOuter_QueryInterface(This, riid, ppvObj);
284 static ULONG WINAPI MediaSeekingPassThru_AddRef(IMediaSeeking *iface)
286 PassThruImpl *This = impl_from_IMediaSeeking(iface);
288 TRACE("(%p/%p)->()\n", iface, This);
290 return SeekOuter_AddRef(This);
293 static ULONG WINAPI MediaSeekingPassThru_Release(IMediaSeeking *iface)
295 PassThruImpl *This = impl_from_IMediaSeeking(iface);
297 TRACE("(%p/%p)->()\n", iface, This);
299 return SeekOuter_Release(This);
302 static HRESULT get_connected(PassThruImpl *This, REFIID riid, LPVOID *ppvObj) {
303 HRESULT hr;
304 IPin *pin;
305 *ppvObj = NULL;
306 hr = IPin_ConnectedTo(This->pin, &pin);
307 if (FAILED(hr))
308 return VFW_E_NOT_CONNECTED;
309 hr = IPin_QueryInterface(pin, riid, ppvObj);
310 IPin_Release(pin);
311 if (FAILED(hr))
312 hr = E_NOTIMPL;
313 return hr;
316 static HRESULT WINAPI MediaSeekingPassThru_GetCapabilities(IMediaSeeking * iface, DWORD * pCapabilities)
318 PassThruImpl *This = impl_from_IMediaSeeking(iface);
319 IMediaSeeking *seek;
320 HRESULT hr;
321 TRACE("(%p/%p)->(%p)\n", iface, This, pCapabilities);
322 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
323 if (SUCCEEDED(hr)) {
324 hr = IMediaSeeking_GetCapabilities(seek, pCapabilities);
325 IMediaSeeking_Release(seek);
327 else
328 return E_NOTIMPL;
329 return hr;
332 static HRESULT WINAPI MediaSeekingPassThru_CheckCapabilities(IMediaSeeking * iface, DWORD * pCapabilities)
334 PassThruImpl *This = impl_from_IMediaSeeking(iface);
335 IMediaSeeking *seek;
336 HRESULT hr;
337 TRACE("(%p/%p)->(%p)\n", iface, This, pCapabilities);
338 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
339 if (SUCCEEDED(hr)) {
340 hr = IMediaSeeking_CheckCapabilities(seek, pCapabilities);
341 IMediaSeeking_Release(seek);
343 else
344 return E_NOTIMPL;
345 return hr;
348 static HRESULT WINAPI MediaSeekingPassThru_IsFormatSupported(IMediaSeeking * iface, const GUID * pFormat)
350 PassThruImpl *This = impl_from_IMediaSeeking(iface);
351 IMediaSeeking *seek;
352 HRESULT hr;
353 TRACE("(%p/%p)->(%s)\n", iface, This, debugstr_guid(pFormat));
354 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
355 if (SUCCEEDED(hr)) {
356 hr = IMediaSeeking_IsFormatSupported(seek, pFormat);
357 IMediaSeeking_Release(seek);
359 else
360 return E_NOTIMPL;
361 return hr;
364 static HRESULT WINAPI MediaSeekingPassThru_QueryPreferredFormat(IMediaSeeking * iface, GUID * pFormat)
366 PassThruImpl *This = impl_from_IMediaSeeking(iface);
367 IMediaSeeking *seek;
368 HRESULT hr;
369 TRACE("(%p/%p)->(%p)\n", iface, This, pFormat);
370 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
371 if (SUCCEEDED(hr)) {
372 hr = IMediaSeeking_QueryPreferredFormat(seek, pFormat);
373 IMediaSeeking_Release(seek);
375 else
376 return E_NOTIMPL;
377 return hr;
380 static HRESULT WINAPI MediaSeekingPassThru_GetTimeFormat(IMediaSeeking * iface, GUID * pFormat)
382 PassThruImpl *This = impl_from_IMediaSeeking(iface);
383 IMediaSeeking *seek;
384 HRESULT hr;
385 TRACE("(%p/%p)->(%p)\n", iface, This, pFormat);
386 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
387 if (SUCCEEDED(hr)) {
388 hr = IMediaSeeking_GetTimeFormat(seek, pFormat);
389 IMediaSeeking_Release(seek);
391 else
392 return E_NOTIMPL;
393 return hr;
396 static HRESULT WINAPI MediaSeekingPassThru_IsUsingTimeFormat(IMediaSeeking * iface, const GUID * pFormat)
398 PassThruImpl *This = impl_from_IMediaSeeking(iface);
399 IMediaSeeking *seek;
400 HRESULT hr;
401 TRACE("(%p/%p)->(%s)\n", iface, This, debugstr_guid(pFormat));
402 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
403 if (SUCCEEDED(hr)) {
404 hr = IMediaSeeking_IsUsingTimeFormat(seek, pFormat);
405 IMediaSeeking_Release(seek);
407 else
408 return E_NOTIMPL;
409 return hr;
412 static HRESULT WINAPI MediaSeekingPassThru_SetTimeFormat(IMediaSeeking * iface, const GUID * pFormat)
414 PassThruImpl *This = impl_from_IMediaSeeking(iface);
415 IMediaSeeking *seek;
416 HRESULT hr;
417 TRACE("(%p/%p)->(%s)\n", iface, This, debugstr_guid(pFormat));
418 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
419 if (SUCCEEDED(hr)) {
420 hr = IMediaSeeking_SetTimeFormat(seek, pFormat);
421 IMediaSeeking_Release(seek);
423 else
424 return E_NOTIMPL;
425 return hr;
428 static HRESULT WINAPI MediaSeekingPassThru_GetDuration(IMediaSeeking * iface, LONGLONG * pDuration)
430 PassThruImpl *This = impl_from_IMediaSeeking(iface);
431 IMediaSeeking *seek;
432 HRESULT hr;
433 TRACE("(%p/%p)->(%p)\n", iface, This, pDuration);
434 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
435 if (SUCCEEDED(hr)) {
436 hr = IMediaSeeking_GetDuration(seek, pDuration);
437 IMediaSeeking_Release(seek);
439 else
440 return E_NOTIMPL;
441 return hr;
444 static HRESULT WINAPI MediaSeekingPassThru_GetStopPosition(IMediaSeeking * iface, LONGLONG * pStop)
446 PassThruImpl *This = impl_from_IMediaSeeking(iface);
447 IMediaSeeking *seek;
448 HRESULT hr;
449 TRACE("(%p/%p)->(%p)\n", iface, This, pStop);
450 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
451 if (SUCCEEDED(hr)) {
452 hr = IMediaSeeking_GetStopPosition(seek, pStop);
453 IMediaSeeking_Release(seek);
455 else
456 return E_NOTIMPL;
457 return hr;
460 static HRESULT WINAPI MediaSeekingPassThru_GetCurrentPosition(IMediaSeeking * iface, LONGLONG * pCurrent)
462 PassThruImpl *This = impl_from_IMediaSeeking(iface);
463 IMediaSeeking *seek;
464 HRESULT hr = S_OK;
465 TRACE("(%p/%p)->(%p)\n", iface, This, pCurrent);
466 if (!pCurrent)
467 return E_POINTER;
468 EnterCriticalSection(&This->time_cs);
469 if (This->timevalid)
470 *pCurrent = This->time_earliest;
471 else
472 hr = E_FAIL;
473 LeaveCriticalSection(&This->time_cs);
474 if (SUCCEEDED(hr)) {
475 hr = IMediaSeeking_ConvertTimeFormat(iface, pCurrent, NULL, *pCurrent, &TIME_FORMAT_MEDIA_TIME);
476 return hr;
478 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
479 if (SUCCEEDED(hr)) {
480 hr = IMediaSeeking_GetCurrentPosition(seek, pCurrent);
481 IMediaSeeking_Release(seek);
483 else
484 return E_NOTIMPL;
485 return hr;
488 static HRESULT WINAPI MediaSeekingPassThru_ConvertTimeFormat(IMediaSeeking * iface, LONGLONG * pTarget, const GUID * pTargetFormat, LONGLONG Source, const GUID * pSourceFormat)
490 PassThruImpl *This = impl_from_IMediaSeeking(iface);
491 IMediaSeeking *seek;
492 HRESULT hr;
493 TRACE("(%p/%p)->(%p,%s,%x%08x,%s)\n", iface, This, pTarget, debugstr_guid(pTargetFormat), (DWORD)(Source>>32), (DWORD)Source, debugstr_guid(pSourceFormat));
494 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
495 if (SUCCEEDED(hr)) {
496 hr = IMediaSeeking_ConvertTimeFormat(seek, pTarget, pTargetFormat, Source, pSourceFormat);
497 IMediaSeeking_Release(seek);
499 else
500 return E_NOTIMPL;
501 return hr;
504 static HRESULT WINAPI MediaSeekingPassThru_SetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, DWORD dwCurrentFlags, LONGLONG * pStop, DWORD dwStopFlags)
506 PassThruImpl *This = impl_from_IMediaSeeking(iface);
507 IMediaSeeking *seek;
508 HRESULT hr;
509 TRACE("(%p/%p)->(%p,%x,%p,%x)\n", iface, This, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
510 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
511 if (SUCCEEDED(hr)) {
512 hr = IMediaSeeking_SetPositions(seek, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
513 IMediaSeeking_Release(seek);
514 } else if (hr == VFW_E_NOT_CONNECTED)
515 hr = S_OK;
516 return hr;
519 static HRESULT WINAPI MediaSeekingPassThru_GetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, LONGLONG * pStop)
521 PassThruImpl *This = impl_from_IMediaSeeking(iface);
522 IMediaSeeking *seek;
523 HRESULT hr;
524 TRACE("(%p/%p)->(%p, %p)\n", iface, This, pCurrent, pStop);
525 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
526 if (SUCCEEDED(hr)) {
527 hr = IMediaSeeking_GetPositions(seek, pCurrent, pStop);
528 IMediaSeeking_Release(seek);
530 else
531 return E_NOTIMPL;
532 return hr;
535 static HRESULT WINAPI MediaSeekingPassThru_GetAvailable(IMediaSeeking * iface, LONGLONG * pEarliest, LONGLONG * pLatest)
537 PassThruImpl *This = impl_from_IMediaSeeking(iface);
538 IMediaSeeking *seek;
539 HRESULT hr;
540 TRACE("(%p/%p)->(%p,%p)\n", iface, This, pEarliest, pLatest);
541 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
542 if (SUCCEEDED(hr)) {
543 hr = IMediaSeeking_GetAvailable(seek, pEarliest, pLatest);
544 IMediaSeeking_Release(seek);
546 else
547 return E_NOTIMPL;
548 return hr;
551 static HRESULT WINAPI MediaSeekingPassThru_SetRate(IMediaSeeking * iface, double dRate)
553 PassThruImpl *This = impl_from_IMediaSeeking(iface);
554 IMediaSeeking *seek;
555 HRESULT hr;
556 TRACE("(%p/%p)->(%e)\n", iface, This, dRate);
557 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
558 if (SUCCEEDED(hr)) {
559 hr = IMediaSeeking_SetRate(seek, dRate);
560 IMediaSeeking_Release(seek);
562 else
563 return E_NOTIMPL;
564 return hr;
567 static HRESULT WINAPI MediaSeekingPassThru_GetRate(IMediaSeeking * iface, double * dRate)
569 PassThruImpl *This = impl_from_IMediaSeeking(iface);
570 IMediaSeeking *seek;
571 HRESULT hr;
572 TRACE("(%p/%p)->(%p)\n", iface, This, dRate);
573 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
574 if (SUCCEEDED(hr)) {
575 hr = IMediaSeeking_GetRate(seek, dRate);
576 IMediaSeeking_Release(seek);
578 else
579 return E_NOTIMPL;
580 return hr;
583 static HRESULT WINAPI MediaSeekingPassThru_GetPreroll(IMediaSeeking * iface, LONGLONG * pPreroll)
585 PassThruImpl *This = impl_from_IMediaSeeking(iface);
586 IMediaSeeking *seek;
587 HRESULT hr;
588 TRACE("(%p)\n", pPreroll);
589 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
590 if (SUCCEEDED(hr)) {
591 hr = IMediaSeeking_GetPreroll(seek, pPreroll);
592 IMediaSeeking_Release(seek);
594 else
595 return E_NOTIMPL;
596 return hr;
599 HRESULT WINAPI RendererPosPassThru_RegisterMediaTime(IUnknown *iface, REFERENCE_TIME start)
601 PassThruImpl *This = impl_from_IUnknown_inner(iface);
602 EnterCriticalSection(&This->time_cs);
603 This->time_earliest = start;
604 This->timevalid = TRUE;
605 LeaveCriticalSection(&This->time_cs);
606 return S_OK;
609 HRESULT WINAPI RendererPosPassThru_ResetMediaTime(IUnknown *iface)
611 PassThruImpl *This = impl_from_IUnknown_inner(iface);
612 EnterCriticalSection(&This->time_cs);
613 This->timevalid = FALSE;
614 LeaveCriticalSection(&This->time_cs);
615 return S_OK;
618 HRESULT WINAPI RendererPosPassThru_EOS(IUnknown *iface)
620 PassThruImpl *This = impl_from_IUnknown_inner(iface);
621 REFERENCE_TIME time;
622 HRESULT hr;
623 hr = IMediaSeeking_GetStopPosition(&This->IMediaSeeking_iface, &time);
624 EnterCriticalSection(&This->time_cs);
625 if (SUCCEEDED(hr)) {
626 This->timevalid = TRUE;
627 This->time_earliest = time;
628 } else
629 This->timevalid = FALSE;
630 LeaveCriticalSection(&This->time_cs);
631 return hr;
634 static const IMediaSeekingVtbl IMediaSeekingPassThru_Vtbl =
636 MediaSeekingPassThru_QueryInterface,
637 MediaSeekingPassThru_AddRef,
638 MediaSeekingPassThru_Release,
639 MediaSeekingPassThru_GetCapabilities,
640 MediaSeekingPassThru_CheckCapabilities,
641 MediaSeekingPassThru_IsFormatSupported,
642 MediaSeekingPassThru_QueryPreferredFormat,
643 MediaSeekingPassThru_GetTimeFormat,
644 MediaSeekingPassThru_IsUsingTimeFormat,
645 MediaSeekingPassThru_SetTimeFormat,
646 MediaSeekingPassThru_GetDuration,
647 MediaSeekingPassThru_GetStopPosition,
648 MediaSeekingPassThru_GetCurrentPosition,
649 MediaSeekingPassThru_ConvertTimeFormat,
650 MediaSeekingPassThru_SetPositions,
651 MediaSeekingPassThru_GetPositions,
652 MediaSeekingPassThru_GetAvailable,
653 MediaSeekingPassThru_SetRate,
654 MediaSeekingPassThru_GetRate,
655 MediaSeekingPassThru_GetPreroll
658 static HRESULT WINAPI MediaPositionPassThru_QueryInterface(IMediaPosition *iface, REFIID riid, LPVOID *ppvObj)
660 PassThruImpl *This = impl_from_IMediaPosition(iface);
662 TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj);
664 return SeekOuter_QueryInterface(This, riid, ppvObj);
667 static ULONG WINAPI MediaPositionPassThru_AddRef(IMediaPosition *iface)
669 PassThruImpl *This = impl_from_IMediaPosition(iface);
671 TRACE("(%p/%p)->()\n", iface, This);
673 return SeekOuter_AddRef(This);
676 static ULONG WINAPI MediaPositionPassThru_Release(IMediaPosition *iface)
678 PassThruImpl *This = impl_from_IMediaPosition(iface);
680 TRACE("(%p/%p)->()\n", iface, This);
682 return SeekOuter_Release(This);
685 static HRESULT WINAPI MediaPositionPassThru_GetTypeInfoCount(IMediaPosition *iface, UINT*pctinfo)
687 PassThruImpl *This = impl_from_IMediaPosition(iface);
689 return BaseDispatchImpl_GetTypeInfoCount(&This->baseDispatch, pctinfo);
692 static HRESULT WINAPI MediaPositionPassThru_GetTypeInfo(IMediaPosition *iface, UINT iTInfo, LCID lcid, ITypeInfo**ppTInfo)
694 PassThruImpl *This = impl_from_IMediaPosition(iface);
696 return BaseDispatchImpl_GetTypeInfo(&This->baseDispatch, &IID_NULL, iTInfo, lcid, ppTInfo);
699 static HRESULT WINAPI MediaPositionPassThru_GetIDsOfNames(IMediaPosition *iface, REFIID riid, LPOLESTR*rgszNames, UINT cNames, LCID lcid, DISPID*rgDispId)
701 PassThruImpl *This = impl_from_IMediaPosition(iface);
703 return BaseDispatchImpl_GetIDsOfNames(&This->baseDispatch, riid, rgszNames, cNames, lcid, rgDispId);
706 static HRESULT WINAPI MediaPositionPassThru_Invoke(IMediaPosition *iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS*pDispParams, VARIANT*pVarResult, EXCEPINFO*pExepInfo, UINT*puArgErr)
708 PassThruImpl *This = impl_from_IMediaPosition(iface);
709 HRESULT hr = S_OK;
710 ITypeInfo *pTypeInfo;
712 hr = BaseDispatchImpl_GetTypeInfo(&This->baseDispatch, riid, 1, lcid, &pTypeInfo);
713 if (SUCCEEDED(hr))
715 hr = ITypeInfo_Invoke(pTypeInfo, &This->IMediaPosition_iface, dispIdMember, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
716 ITypeInfo_Release(pTypeInfo);
719 return hr;
722 static HRESULT WINAPI MediaPositionPassThru_get_Duration(IMediaPosition *iface, REFTIME *plength)
724 PassThruImpl *This = impl_from_IMediaPosition(iface);
725 IMediaPosition *pos;
726 HRESULT hr;
728 TRACE("(%p)\n", plength);
730 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
731 if (SUCCEEDED(hr)) {
732 hr = IMediaPosition_get_Duration(pos, plength);
733 IMediaPosition_Release(pos);
735 else
736 return E_NOTIMPL;
737 return hr;
740 static HRESULT WINAPI MediaPositionPassThru_put_CurrentPosition(IMediaPosition *iface, REFTIME llTime)
742 PassThruImpl *This = impl_from_IMediaPosition(iface);
743 IMediaPosition *pos;
744 HRESULT hr;
746 TRACE("(%s)\n", wine_dbgstr_longlong(llTime));
748 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
749 if (SUCCEEDED(hr)) {
750 hr = IMediaPosition_put_CurrentPosition(pos, llTime);
751 IMediaPosition_Release(pos);
753 else
754 return E_NOTIMPL;
755 return hr;
758 static HRESULT WINAPI MediaPositionPassThru_get_CurrentPosition(IMediaPosition *iface, REFTIME *pllTime)
760 PassThruImpl *This = impl_from_IMediaPosition(iface);
761 IMediaPosition *pos;
762 HRESULT hr;
764 TRACE("(%p)\n", pllTime);
766 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
767 if (SUCCEEDED(hr)) {
768 hr = IMediaPosition_get_CurrentPosition(pos, pllTime);
769 IMediaPosition_Release(pos);
771 else
772 return E_NOTIMPL;
773 return hr;
776 static HRESULT WINAPI MediaPositionPassThru_get_StopTime(IMediaPosition *iface, REFTIME *pllTime)
778 PassThruImpl *This = impl_from_IMediaPosition(iface);
779 IMediaPosition *pos;
780 HRESULT hr;
782 TRACE("(%p)\n", pllTime);
784 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
785 if (SUCCEEDED(hr)) {
786 hr = IMediaPosition_get_StopTime(pos, pllTime);
787 IMediaPosition_Release(pos);
789 else
790 return E_NOTIMPL;
791 return hr;
794 static HRESULT WINAPI MediaPositionPassThru_put_StopTime(IMediaPosition *iface, REFTIME llTime)
796 PassThruImpl *This = impl_from_IMediaPosition(iface);
797 IMediaPosition *pos;
798 HRESULT hr;
800 TRACE("(%s)\n", wine_dbgstr_longlong(llTime));
802 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
803 if (SUCCEEDED(hr)) {
804 hr = IMediaPosition_put_StopTime(pos, llTime);
805 IMediaPosition_Release(pos);
807 else
808 return E_NOTIMPL;
809 return hr;
812 static HRESULT WINAPI MediaPositionPassThru_get_PrerollTime(IMediaPosition *iface, REFTIME *pllTime)
814 PassThruImpl *This = impl_from_IMediaPosition(iface);
815 IMediaPosition *pos;
816 HRESULT hr;
818 TRACE("(%p)\n", pllTime);
820 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
821 if (SUCCEEDED(hr)) {
822 hr = IMediaPosition_get_PrerollTime(pos, pllTime);
823 IMediaPosition_Release(pos);
825 else
826 return E_NOTIMPL;
827 return hr;
830 static HRESULT WINAPI MediaPositionPassThru_put_PrerollTime(IMediaPosition *iface, REFTIME llTime)
832 PassThruImpl *This = impl_from_IMediaPosition(iface);
833 IMediaPosition *pos;
834 HRESULT hr;
836 TRACE("(%s)\n", wine_dbgstr_longlong(llTime));
838 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
839 if (SUCCEEDED(hr)) {
840 hr = IMediaPosition_put_PrerollTime(pos, llTime);
841 IMediaPosition_Release(pos);
843 else
844 return E_NOTIMPL;
845 return hr;
848 static HRESULT WINAPI MediaPositionPassThru_put_Rate(IMediaPosition *iface, double dRate)
850 PassThruImpl *This = impl_from_IMediaPosition(iface);
851 IMediaPosition *pos;
852 HRESULT hr;
854 TRACE("(%f)\n", dRate);
856 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
857 if (SUCCEEDED(hr)) {
858 hr = IMediaPosition_put_Rate(pos, dRate);
859 IMediaPosition_Release(pos);
861 else
862 return E_NOTIMPL;
863 return hr;
866 static HRESULT WINAPI MediaPositionPassThru_get_Rate(IMediaPosition *iface, double *pdRate)
868 PassThruImpl *This = impl_from_IMediaPosition(iface);
869 IMediaPosition *pos;
870 HRESULT hr;
872 TRACE("(%p)\n", pdRate);
874 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
875 if (SUCCEEDED(hr)) {
876 hr = IMediaPosition_get_Rate(pos, pdRate);
877 IMediaPosition_Release(pos);
879 else
880 return E_NOTIMPL;
881 return hr;
884 static HRESULT WINAPI MediaPositionPassThru_CanSeekForward(IMediaPosition *iface, LONG *pCanSeekForward)
886 PassThruImpl *This = impl_from_IMediaPosition(iface);
887 IMediaPosition *pos;
888 HRESULT hr;
890 TRACE("(%p)\n", pCanSeekForward);
892 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
893 if (SUCCEEDED(hr)) {
894 hr = IMediaPosition_CanSeekForward(pos, pCanSeekForward);
895 IMediaPosition_Release(pos);
897 else
898 return E_NOTIMPL;
899 return hr;
902 static HRESULT WINAPI MediaPositionPassThru_CanSeekBackward(IMediaPosition *iface, LONG *pCanSeekBackward)
904 PassThruImpl *This = impl_from_IMediaPosition(iface);
905 IMediaPosition *pos;
906 HRESULT hr;
908 TRACE("(%p)\n", pCanSeekBackward);
910 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
911 if (SUCCEEDED(hr)) {
912 hr = IMediaPosition_CanSeekBackward(pos, pCanSeekBackward);
913 IMediaPosition_Release(pos);
915 else
916 return E_NOTIMPL;
917 return hr;
920 static const IMediaPositionVtbl IMediaPositionPassThru_Vtbl =
922 MediaPositionPassThru_QueryInterface,
923 MediaPositionPassThru_AddRef,
924 MediaPositionPassThru_Release,
925 MediaPositionPassThru_GetTypeInfoCount,
926 MediaPositionPassThru_GetTypeInfo,
927 MediaPositionPassThru_GetIDsOfNames,
928 MediaPositionPassThru_Invoke,
929 MediaPositionPassThru_get_Duration,
930 MediaPositionPassThru_put_CurrentPosition,
931 MediaPositionPassThru_get_CurrentPosition,
932 MediaPositionPassThru_get_StopTime,
933 MediaPositionPassThru_put_StopTime,
934 MediaPositionPassThru_get_PrerollTime,
935 MediaPositionPassThru_put_PrerollTime,
936 MediaPositionPassThru_put_Rate,
937 MediaPositionPassThru_get_Rate,
938 MediaPositionPassThru_CanSeekForward,
939 MediaPositionPassThru_CanSeekBackward