joy.cpl: Correct joystick testing thread behavior.
[wine.git] / dlls / strmbase / pospass.c
blob71c1dc67d17cf85afcadbc7cf8631401c22f6b70
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), %p)\n", This, debugstr_guid(riid), 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((IUnknown *)&(This->IUnknown_inner));
156 hr = IUnknown_QueryInterface((IUnknown *)&(This->IUnknown_inner), riid, ppv);
157 IUnknown_Release((IUnknown *)&(This->IUnknown_inner));
158 This->bAggregatable = TRUE;
159 return hr;
162 *ppv = NULL;
163 return E_NOINTERFACE;
166 return IUnknown_QueryInterface((IUnknown *)&(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((IUnknown *)&(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((IUnknown *)&(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), %p)\n", This, iface, debugstr_guid(riid), 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);
240 IUnknown_QueryInterface(*ppPassThru, &IID_ISeekingPassThru, (void**)&passthru);
241 hr = ISeekingPassThru_Init(passthru, bRenderer, pPin);
242 ISeekingPassThru_Release(passthru);
244 return hr;
247 HRESULT WINAPI PosPassThru_Construct(IUnknown *pUnkOuter, LPVOID *ppPassThru)
249 PassThruImpl *fimpl;
251 TRACE("(%p,%p)\n", pUnkOuter, ppPassThru);
253 *ppPassThru = fimpl = CoTaskMemAlloc(sizeof(*fimpl));
254 if (!fimpl)
255 return E_OUTOFMEMORY;
257 fimpl->outer_unk = pUnkOuter;
258 fimpl->bUnkOuterValid = FALSE;
259 fimpl->bAggregatable = FALSE;
260 fimpl->IUnknown_inner.lpVtbl = &IInner_VTable;
261 fimpl->ISeekingPassThru_iface.lpVtbl = &ISeekingPassThru_Vtbl;
262 fimpl->IMediaSeeking_iface.lpVtbl = &IMediaSeekingPassThru_Vtbl;
263 fimpl->IMediaPosition_iface.lpVtbl = &IMediaPositionPassThru_Vtbl;
264 fimpl->ref = 1;
265 fimpl->pin = NULL;
266 fimpl->timevalid = 0;
267 InitializeCriticalSection(&fimpl->time_cs);
268 fimpl->time_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": PassThruImpl.time_cs");
269 BaseDispatch_Init(&fimpl->baseDispatch, &IID_IMediaPosition);
270 return S_OK;
273 static HRESULT WINAPI MediaSeekingPassThru_QueryInterface(IMediaSeeking *iface, REFIID riid, LPVOID *ppvObj)
275 PassThruImpl *This = impl_from_IMediaSeeking(iface);
277 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
279 return SeekOuter_QueryInterface(This, riid, ppvObj);
282 static ULONG WINAPI MediaSeekingPassThru_AddRef(IMediaSeeking *iface)
284 PassThruImpl *This = impl_from_IMediaSeeking(iface);
286 TRACE("(%p/%p)->()\n", iface, This);
288 return SeekOuter_AddRef(This);
291 static ULONG WINAPI MediaSeekingPassThru_Release(IMediaSeeking *iface)
293 PassThruImpl *This = impl_from_IMediaSeeking(iface);
295 TRACE("(%p/%p)->()\n", iface, This);
297 return SeekOuter_Release(This);
300 static HRESULT get_connected(PassThruImpl *This, REFIID riid, LPVOID *ppvObj) {
301 HRESULT hr;
302 IPin *pin;
303 *ppvObj = NULL;
304 hr = IPin_ConnectedTo(This->pin, &pin);
305 if (FAILED(hr))
306 return VFW_E_NOT_CONNECTED;
307 hr = IPin_QueryInterface(pin, riid, ppvObj);
308 IPin_Release(pin);
309 if (FAILED(hr))
310 hr = E_NOTIMPL;
311 return hr;
314 static HRESULT WINAPI MediaSeekingPassThru_GetCapabilities(IMediaSeeking * iface, DWORD * pCapabilities)
316 PassThruImpl *This = impl_from_IMediaSeeking(iface);
317 IMediaSeeking *seek;
318 HRESULT hr;
319 TRACE("(%p/%p)->(%p)\n", iface, This, pCapabilities);
320 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
321 if (SUCCEEDED(hr)) {
322 hr = IMediaSeeking_GetCapabilities(seek, pCapabilities);
323 IMediaSeeking_Release(seek);
325 else
326 return E_NOTIMPL;
327 return hr;
330 static HRESULT WINAPI MediaSeekingPassThru_CheckCapabilities(IMediaSeeking * iface, DWORD * pCapabilities)
332 PassThruImpl *This = impl_from_IMediaSeeking(iface);
333 IMediaSeeking *seek;
334 HRESULT hr;
335 TRACE("(%p/%p)->(%p)\n", iface, This, pCapabilities);
336 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
337 if (SUCCEEDED(hr)) {
338 hr = IMediaSeeking_CheckCapabilities(seek, pCapabilities);
339 IMediaSeeking_Release(seek);
341 else
342 return E_NOTIMPL;
343 return hr;
346 static HRESULT WINAPI MediaSeekingPassThru_IsFormatSupported(IMediaSeeking * iface, const GUID * pFormat)
348 PassThruImpl *This = impl_from_IMediaSeeking(iface);
349 IMediaSeeking *seek;
350 HRESULT hr;
351 TRACE("(%p/%p)->(%s)\n", iface, This, debugstr_guid(pFormat));
352 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
353 if (SUCCEEDED(hr)) {
354 hr = IMediaSeeking_IsFormatSupported(seek, pFormat);
355 IMediaSeeking_Release(seek);
357 else
358 return E_NOTIMPL;
359 return hr;
362 static HRESULT WINAPI MediaSeekingPassThru_QueryPreferredFormat(IMediaSeeking * iface, GUID * pFormat)
364 PassThruImpl *This = impl_from_IMediaSeeking(iface);
365 IMediaSeeking *seek;
366 HRESULT hr;
367 TRACE("(%p/%p)->(%p)\n", iface, This, pFormat);
368 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
369 if (SUCCEEDED(hr)) {
370 hr = IMediaSeeking_QueryPreferredFormat(seek, pFormat);
371 IMediaSeeking_Release(seek);
373 else
374 return E_NOTIMPL;
375 return hr;
378 static HRESULT WINAPI MediaSeekingPassThru_GetTimeFormat(IMediaSeeking * iface, GUID * pFormat)
380 PassThruImpl *This = impl_from_IMediaSeeking(iface);
381 IMediaSeeking *seek;
382 HRESULT hr;
383 TRACE("(%p/%p)->(%p)\n", iface, This, pFormat);
384 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
385 if (SUCCEEDED(hr)) {
386 hr = IMediaSeeking_GetTimeFormat(seek, pFormat);
387 IMediaSeeking_Release(seek);
389 else
390 return E_NOTIMPL;
391 return hr;
394 static HRESULT WINAPI MediaSeekingPassThru_IsUsingTimeFormat(IMediaSeeking * iface, const GUID * pFormat)
396 PassThruImpl *This = impl_from_IMediaSeeking(iface);
397 IMediaSeeking *seek;
398 HRESULT hr;
399 TRACE("(%p/%p)->(%s)\n", iface, This, debugstr_guid(pFormat));
400 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
401 if (SUCCEEDED(hr)) {
402 hr = IMediaSeeking_IsUsingTimeFormat(seek, pFormat);
403 IMediaSeeking_Release(seek);
405 else
406 return E_NOTIMPL;
407 return hr;
410 static HRESULT WINAPI MediaSeekingPassThru_SetTimeFormat(IMediaSeeking * iface, const GUID * pFormat)
412 PassThruImpl *This = impl_from_IMediaSeeking(iface);
413 IMediaSeeking *seek;
414 HRESULT hr;
415 TRACE("(%p/%p)->(%s)\n", iface, This, debugstr_guid(pFormat));
416 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
417 if (SUCCEEDED(hr)) {
418 hr = IMediaSeeking_SetTimeFormat(seek, pFormat);
419 IMediaSeeking_Release(seek);
421 else
422 return E_NOTIMPL;
423 return hr;
426 static HRESULT WINAPI MediaSeekingPassThru_GetDuration(IMediaSeeking * iface, LONGLONG * pDuration)
428 PassThruImpl *This = impl_from_IMediaSeeking(iface);
429 IMediaSeeking *seek;
430 HRESULT hr;
431 TRACE("(%p/%p)->(%p)\n", iface, This, pDuration);
432 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
433 if (SUCCEEDED(hr)) {
434 hr = IMediaSeeking_GetDuration(seek, pDuration);
435 IMediaSeeking_Release(seek);
437 else
438 return E_NOTIMPL;
439 return hr;
442 static HRESULT WINAPI MediaSeekingPassThru_GetStopPosition(IMediaSeeking * iface, LONGLONG * pStop)
444 PassThruImpl *This = impl_from_IMediaSeeking(iface);
445 IMediaSeeking *seek;
446 HRESULT hr;
447 TRACE("(%p/%p)->(%p)\n", iface, This, pStop);
448 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
449 if (SUCCEEDED(hr)) {
450 hr = IMediaSeeking_GetStopPosition(seek, pStop);
451 IMediaSeeking_Release(seek);
453 else
454 return E_NOTIMPL;
455 return hr;
458 static HRESULT WINAPI MediaSeekingPassThru_GetCurrentPosition(IMediaSeeking * iface, LONGLONG * pCurrent)
460 PassThruImpl *This = impl_from_IMediaSeeking(iface);
461 IMediaSeeking *seek;
462 HRESULT hr = S_OK;
463 TRACE("(%p/%p)->(%p)\n", iface, This, pCurrent);
464 if (!pCurrent)
465 return E_POINTER;
466 EnterCriticalSection(&This->time_cs);
467 if (This->timevalid)
468 *pCurrent = This->time_earliest;
469 else
470 hr = E_FAIL;
471 LeaveCriticalSection(&This->time_cs);
472 if (SUCCEEDED(hr)) {
473 hr = IMediaSeeking_ConvertTimeFormat(iface, pCurrent, NULL, *pCurrent, &TIME_FORMAT_MEDIA_TIME);
474 return hr;
476 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
477 if (SUCCEEDED(hr)) {
478 hr = IMediaSeeking_GetCurrentPosition(seek, pCurrent);
479 IMediaSeeking_Release(seek);
481 else
482 return E_NOTIMPL;
483 return hr;
486 static HRESULT WINAPI MediaSeekingPassThru_ConvertTimeFormat(IMediaSeeking * iface, LONGLONG * pTarget, const GUID * pTargetFormat, LONGLONG Source, const GUID * pSourceFormat)
488 PassThruImpl *This = impl_from_IMediaSeeking(iface);
489 IMediaSeeking *seek;
490 HRESULT hr;
491 TRACE("(%p/%p)->(%p,%s,%x%08x,%s)\n", iface, This, pTarget, debugstr_guid(pTargetFormat), (DWORD)(Source>>32), (DWORD)Source, debugstr_guid(pSourceFormat));
492 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
493 if (SUCCEEDED(hr)) {
494 hr = IMediaSeeking_ConvertTimeFormat(seek, pTarget, pTargetFormat, Source, pSourceFormat);
495 IMediaSeeking_Release(seek);
497 else
498 return E_NOTIMPL;
499 return hr;
502 static HRESULT WINAPI MediaSeekingPassThru_SetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, DWORD dwCurrentFlags, LONGLONG * pStop, DWORD dwStopFlags)
504 PassThruImpl *This = impl_from_IMediaSeeking(iface);
505 IMediaSeeking *seek;
506 HRESULT hr;
507 TRACE("(%p/%p)->(%p,%x,%p,%x)\n", iface, This, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
508 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
509 if (SUCCEEDED(hr)) {
510 hr = IMediaSeeking_SetPositions(seek, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
511 IMediaSeeking_Release(seek);
512 } else if (hr == VFW_E_NOT_CONNECTED)
513 hr = S_OK;
514 return hr;
517 static HRESULT WINAPI MediaSeekingPassThru_GetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, LONGLONG * pStop)
519 PassThruImpl *This = impl_from_IMediaSeeking(iface);
520 IMediaSeeking *seek;
521 HRESULT hr;
522 TRACE("(%p/%p)->(%p, %p)\n", iface, This, pCurrent, pStop);
523 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
524 if (SUCCEEDED(hr)) {
525 hr = IMediaSeeking_GetPositions(seek, pCurrent, pStop);
526 IMediaSeeking_Release(seek);
528 else
529 return E_NOTIMPL;
530 return hr;
533 static HRESULT WINAPI MediaSeekingPassThru_GetAvailable(IMediaSeeking * iface, LONGLONG * pEarliest, LONGLONG * pLatest)
535 PassThruImpl *This = impl_from_IMediaSeeking(iface);
536 IMediaSeeking *seek;
537 HRESULT hr;
538 TRACE("(%p/%p)->(%p,%p)\n", iface, This, pEarliest, pLatest);
539 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
540 if (SUCCEEDED(hr)) {
541 hr = IMediaSeeking_GetAvailable(seek, pEarliest, pLatest);
542 IMediaSeeking_Release(seek);
544 else
545 return E_NOTIMPL;
546 return hr;
549 static HRESULT WINAPI MediaSeekingPassThru_SetRate(IMediaSeeking * iface, double dRate)
551 PassThruImpl *This = impl_from_IMediaSeeking(iface);
552 IMediaSeeking *seek;
553 HRESULT hr;
554 TRACE("(%p/%p)->(%e)\n", iface, This, dRate);
555 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
556 if (SUCCEEDED(hr)) {
557 hr = IMediaSeeking_SetRate(seek, dRate);
558 IMediaSeeking_Release(seek);
560 else
561 return E_NOTIMPL;
562 return hr;
565 static HRESULT WINAPI MediaSeekingPassThru_GetRate(IMediaSeeking * iface, double * dRate)
567 PassThruImpl *This = impl_from_IMediaSeeking(iface);
568 IMediaSeeking *seek;
569 HRESULT hr;
570 TRACE("(%p/%p)->(%p)\n", iface, This, dRate);
571 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
572 if (SUCCEEDED(hr)) {
573 hr = IMediaSeeking_GetRate(seek, dRate);
574 IMediaSeeking_Release(seek);
576 else
577 return E_NOTIMPL;
578 return hr;
581 static HRESULT WINAPI MediaSeekingPassThru_GetPreroll(IMediaSeeking * iface, LONGLONG * pPreroll)
583 PassThruImpl *This = impl_from_IMediaSeeking(iface);
584 IMediaSeeking *seek;
585 HRESULT hr;
586 TRACE("(%p)\n", pPreroll);
587 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
588 if (SUCCEEDED(hr)) {
589 hr = IMediaSeeking_GetPreroll(seek, pPreroll);
590 IMediaSeeking_Release(seek);
592 else
593 return E_NOTIMPL;
594 return hr;
597 HRESULT WINAPI RendererPosPassThru_RegisterMediaTime(IUnknown *iface, REFERENCE_TIME start)
599 PassThruImpl *This = impl_from_IUnknown_inner(iface);
600 EnterCriticalSection(&This->time_cs);
601 This->time_earliest = start;
602 This->timevalid = 1;
603 LeaveCriticalSection(&This->time_cs);
604 return S_OK;
607 HRESULT WINAPI RendererPosPassThru_ResetMediaTime(IUnknown *iface)
609 PassThruImpl *This = impl_from_IUnknown_inner(iface);
610 EnterCriticalSection(&This->time_cs);
611 This->timevalid = 0;
612 LeaveCriticalSection(&This->time_cs);
613 return S_OK;
616 HRESULT WINAPI RendererPosPassThru_EOS(IUnknown *iface)
618 PassThruImpl *This = impl_from_IUnknown_inner(iface);
619 REFERENCE_TIME time;
620 HRESULT hr;
621 hr = IMediaSeeking_GetStopPosition(&This->IMediaSeeking_iface, &time);
622 EnterCriticalSection(&This->time_cs);
623 if (SUCCEEDED(hr)) {
624 This->timevalid = 1;
625 This->time_earliest = time;
626 } else
627 This->timevalid = 0;
628 LeaveCriticalSection(&This->time_cs);
629 return hr;
632 static const IMediaSeekingVtbl IMediaSeekingPassThru_Vtbl =
634 MediaSeekingPassThru_QueryInterface,
635 MediaSeekingPassThru_AddRef,
636 MediaSeekingPassThru_Release,
637 MediaSeekingPassThru_GetCapabilities,
638 MediaSeekingPassThru_CheckCapabilities,
639 MediaSeekingPassThru_IsFormatSupported,
640 MediaSeekingPassThru_QueryPreferredFormat,
641 MediaSeekingPassThru_GetTimeFormat,
642 MediaSeekingPassThru_IsUsingTimeFormat,
643 MediaSeekingPassThru_SetTimeFormat,
644 MediaSeekingPassThru_GetDuration,
645 MediaSeekingPassThru_GetStopPosition,
646 MediaSeekingPassThru_GetCurrentPosition,
647 MediaSeekingPassThru_ConvertTimeFormat,
648 MediaSeekingPassThru_SetPositions,
649 MediaSeekingPassThru_GetPositions,
650 MediaSeekingPassThru_GetAvailable,
651 MediaSeekingPassThru_SetRate,
652 MediaSeekingPassThru_GetRate,
653 MediaSeekingPassThru_GetPreroll
656 static HRESULT WINAPI MediaPositionPassThru_QueryInterface(IMediaPosition *iface, REFIID riid, LPVOID *ppvObj)
658 PassThruImpl *This = impl_from_IMediaPosition(iface);
660 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
662 return SeekOuter_QueryInterface(This, riid, ppvObj);
665 static ULONG WINAPI MediaPositionPassThru_AddRef(IMediaPosition *iface)
667 PassThruImpl *This = impl_from_IMediaPosition(iface);
669 TRACE("(%p/%p)->()\n", iface, This);
671 return SeekOuter_AddRef(This);
674 static ULONG WINAPI MediaPositionPassThru_Release(IMediaPosition *iface)
676 PassThruImpl *This = impl_from_IMediaPosition(iface);
678 TRACE("(%p/%p)->()\n", iface, This);
680 return SeekOuter_Release(This);
683 static HRESULT WINAPI MediaPositionPassThru_GetTypeInfoCount(IMediaPosition *iface, UINT*pctinfo)
685 PassThruImpl *This = impl_from_IMediaPosition(iface);
687 return BaseDispatchImpl_GetTypeInfoCount(&This->baseDispatch, pctinfo);
690 static HRESULT WINAPI MediaPositionPassThru_GetTypeInfo(IMediaPosition *iface, UINT iTInfo, LCID lcid, ITypeInfo**ppTInfo)
692 PassThruImpl *This = impl_from_IMediaPosition(iface);
694 return BaseDispatchImpl_GetTypeInfo(&This->baseDispatch, &IID_NULL, iTInfo, lcid, ppTInfo);
697 static HRESULT WINAPI MediaPositionPassThru_GetIDsOfNames(IMediaPosition *iface, REFIID riid, LPOLESTR*rgszNames, UINT cNames, LCID lcid, DISPID*rgDispId)
699 PassThruImpl *This = impl_from_IMediaPosition(iface);
701 return BaseDispatchImpl_GetIDsOfNames(&This->baseDispatch, riid, rgszNames, cNames, lcid, rgDispId);
704 static HRESULT WINAPI MediaPositionPassThru_Invoke(IMediaPosition *iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS*pDispParams, VARIANT*pVarResult, EXCEPINFO*pExepInfo, UINT*puArgErr)
706 PassThruImpl *This = impl_from_IMediaPosition(iface);
707 HRESULT hr = S_OK;
708 ITypeInfo *pTypeInfo;
710 hr = BaseDispatchImpl_GetTypeInfo(&This->baseDispatch, riid, 1, lcid, &pTypeInfo);
711 if (SUCCEEDED(hr))
713 hr = ITypeInfo_Invoke(pTypeInfo, &This->IMediaPosition_iface, dispIdMember, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
714 ITypeInfo_Release(pTypeInfo);
717 return hr;
720 static HRESULT WINAPI MediaPositionPassThru_get_Duration(IMediaPosition *iface, REFTIME *plength)
722 PassThruImpl *This = impl_from_IMediaPosition(iface);
723 IMediaPosition *pos;
724 HRESULT hr;
726 TRACE("(%p)\n", plength);
728 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
729 if (SUCCEEDED(hr)) {
730 hr = IMediaPosition_get_Duration(pos, plength);
731 IMediaPosition_Release(pos);
733 else
734 return E_NOTIMPL;
735 return hr;
738 static HRESULT WINAPI MediaPositionPassThru_put_CurrentPosition(IMediaPosition *iface, REFTIME llTime)
740 PassThruImpl *This = impl_from_IMediaPosition(iface);
741 IMediaPosition *pos;
742 HRESULT hr;
744 TRACE("(%s)\n", wine_dbgstr_longlong(llTime));
746 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
747 if (SUCCEEDED(hr)) {
748 hr = IMediaPosition_put_CurrentPosition(pos, llTime);
749 IMediaPosition_Release(pos);
751 else
752 return E_NOTIMPL;
753 return hr;
756 static HRESULT WINAPI MediaPositionPassThru_get_CurrentPosition(IMediaPosition *iface, REFTIME *pllTime)
758 PassThruImpl *This = impl_from_IMediaPosition(iface);
759 IMediaPosition *pos;
760 HRESULT hr;
762 TRACE("(%p)\n", pllTime);
764 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
765 if (SUCCEEDED(hr)) {
766 hr = IMediaPosition_get_CurrentPosition(pos, pllTime);
767 IMediaPosition_Release(pos);
769 else
770 return E_NOTIMPL;
771 return hr;
774 static HRESULT WINAPI MediaPositionPassThru_get_StopTime(IMediaPosition *iface, REFTIME *pllTime)
776 PassThruImpl *This = impl_from_IMediaPosition(iface);
777 IMediaPosition *pos;
778 HRESULT hr;
780 TRACE("(%p)\n", pllTime);
782 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
783 if (SUCCEEDED(hr)) {
784 hr = IMediaPosition_get_StopTime(pos, pllTime);
785 IMediaPosition_Release(pos);
787 else
788 return E_NOTIMPL;
789 return hr;
792 static HRESULT WINAPI MediaPositionPassThru_put_StopTime(IMediaPosition *iface, REFTIME llTime)
794 PassThruImpl *This = impl_from_IMediaPosition(iface);
795 IMediaPosition *pos;
796 HRESULT hr;
798 TRACE("(%s)\n", wine_dbgstr_longlong(llTime));
800 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
801 if (SUCCEEDED(hr)) {
802 hr = IMediaPosition_put_StopTime(pos, llTime);
803 IMediaPosition_Release(pos);
805 else
806 return E_NOTIMPL;
807 return hr;
810 static HRESULT WINAPI MediaPositionPassThru_get_PrerollTime(IMediaPosition *iface, REFTIME *pllTime)
812 PassThruImpl *This = impl_from_IMediaPosition(iface);
813 IMediaPosition *pos;
814 HRESULT hr;
816 TRACE("(%p)\n", pllTime);
818 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
819 if (SUCCEEDED(hr)) {
820 hr = IMediaPosition_get_PrerollTime(pos, pllTime);
821 IMediaPosition_Release(pos);
823 else
824 return E_NOTIMPL;
825 return hr;
828 static HRESULT WINAPI MediaPositionPassThru_put_PrerollTime(IMediaPosition *iface, REFTIME llTime)
830 PassThruImpl *This = impl_from_IMediaPosition(iface);
831 IMediaPosition *pos;
832 HRESULT hr;
834 TRACE("(%s)\n", wine_dbgstr_longlong(llTime));
836 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
837 if (SUCCEEDED(hr)) {
838 hr = IMediaPosition_put_PrerollTime(pos, llTime);
839 IMediaPosition_Release(pos);
841 else
842 return E_NOTIMPL;
843 return hr;
846 static HRESULT WINAPI MediaPositionPassThru_put_Rate(IMediaPosition *iface, double dRate)
848 PassThruImpl *This = impl_from_IMediaPosition(iface);
849 IMediaPosition *pos;
850 HRESULT hr;
852 TRACE("(%f)\n", dRate);
854 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
855 if (SUCCEEDED(hr)) {
856 hr = IMediaPosition_put_Rate(pos, dRate);
857 IMediaPosition_Release(pos);
859 else
860 return E_NOTIMPL;
861 return hr;
864 static HRESULT WINAPI MediaPositionPassThru_get_Rate(IMediaPosition *iface, double *pdRate)
866 PassThruImpl *This = impl_from_IMediaPosition(iface);
867 IMediaPosition *pos;
868 HRESULT hr;
870 TRACE("(%p)\n", pdRate);
872 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
873 if (SUCCEEDED(hr)) {
874 hr = IMediaPosition_get_Rate(pos, pdRate);
875 IMediaPosition_Release(pos);
877 else
878 return E_NOTIMPL;
879 return hr;
882 static HRESULT WINAPI MediaPositionPassThru_CanSeekForward(IMediaPosition *iface, LONG *pCanSeekForward)
884 PassThruImpl *This = impl_from_IMediaPosition(iface);
885 IMediaPosition *pos;
886 HRESULT hr;
888 TRACE("(%p)\n", pCanSeekForward);
890 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
891 if (SUCCEEDED(hr)) {
892 hr = IMediaPosition_CanSeekForward(pos, pCanSeekForward);
893 IMediaPosition_Release(pos);
895 else
896 return E_NOTIMPL;
897 return hr;
900 static HRESULT WINAPI MediaPositionPassThru_CanSeekBackward(IMediaPosition *iface, LONG *pCanSeekBackward)
902 PassThruImpl *This = impl_from_IMediaPosition(iface);
903 IMediaPosition *pos;
904 HRESULT hr;
906 TRACE("(%p)\n", pCanSeekBackward);
908 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
909 if (SUCCEEDED(hr)) {
910 hr = IMediaPosition_CanSeekBackward(pos, pCanSeekBackward);
911 IMediaPosition_Release(pos);
913 else
914 return E_NOTIMPL;
915 return hr;
918 static const IMediaPositionVtbl IMediaPositionPassThru_Vtbl =
920 MediaPositionPassThru_QueryInterface,
921 MediaPositionPassThru_AddRef,
922 MediaPositionPassThru_Release,
923 MediaPositionPassThru_GetTypeInfoCount,
924 MediaPositionPassThru_GetTypeInfo,
925 MediaPositionPassThru_GetIDsOfNames,
926 MediaPositionPassThru_Invoke,
927 MediaPositionPassThru_get_Duration,
928 MediaPositionPassThru_put_CurrentPosition,
929 MediaPositionPassThru_get_CurrentPosition,
930 MediaPositionPassThru_get_StopTime,
931 MediaPositionPassThru_put_StopTime,
932 MediaPositionPassThru_get_PrerollTime,
933 MediaPositionPassThru_put_PrerollTime,
934 MediaPositionPassThru_put_Rate,
935 MediaPositionPassThru_get_Rate,
936 MediaPositionPassThru_CanSeekForward,
937 MediaPositionPassThru_CanSeekBackward