71c1dc67d17cf85afcadbc7cf8631401c22f6b70
[reactos.git] / reactos / lib / 3rdparty / strmbase / pospass.c
1 /*
2 * Filter Seeking and Control Interfaces
3 *
4 * Copyright 2003 Robert Shearman
5 * Copyright 2012 Aric Stewart, CodeWeavers
6 *
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.
11 *
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.
16 *
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
20 */
21 /* FIXME: critical sections */
22
23 #define COBJMACROS
24
25 #include "dshow.h"
26 #include "uuids.h"
27
28 #include "wine/debug.h"
29 #include "wine/strmbase.h"
30
31 #include <assert.h>
32
33 WINE_DEFAULT_DEBUG_CHANNEL(strmbase);
34
35 static const IMediaSeekingVtbl IMediaSeekingPassThru_Vtbl;
36 static const IMediaPositionVtbl IMediaPositionPassThru_Vtbl;
37
38 typedef struct PassThruImpl {
39 IUnknown IUnknown_inner;
40 ISeekingPassThru ISeekingPassThru_iface;
41 IMediaSeeking IMediaSeeking_iface;
42 IMediaPosition IMediaPosition_iface;
43 BaseDispatch baseDispatch;
44
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;
55
56 static inline PassThruImpl *impl_from_IUnknown_inner(IUnknown *iface)
57 {
58 return CONTAINING_RECORD(iface, PassThruImpl, IUnknown_inner);
59 }
60
61 static inline PassThruImpl *impl_from_ISeekingPassThru(ISeekingPassThru *iface)
62 {
63 return CONTAINING_RECORD(iface, PassThruImpl, ISeekingPassThru_iface);
64 }
65
66 static inline PassThruImpl *impl_from_IMediaSeeking(IMediaSeeking *iface)
67 {
68 return CONTAINING_RECORD(iface, PassThruImpl, IMediaSeeking_iface);
69 }
70
71 static inline PassThruImpl *impl_from_IMediaPosition(IMediaPosition *iface)
72 {
73 return CONTAINING_RECORD(iface, PassThruImpl, IMediaPosition_iface);
74 }
75
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);
81
82 if (This->bAggregatable)
83 This->bUnkOuterValid = TRUE;
84
85 if (IsEqualGUID(&IID_IUnknown, riid))
86 {
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;
102 }
103
104 IUnknown_AddRef((IUnknown *)(*ppvObj));
105 return S_OK;
106 }
107
108 static ULONG WINAPI SeekInner_AddRef(IUnknown * iface) {
109 PassThruImpl *This = impl_from_IUnknown_inner(iface);
110 ULONG ref = InterlockedIncrement(&This->ref);
111
112 TRACE("(%p)->(): new ref = %d\n", This, ref);
113
114 return ref;
115 }
116
117 static ULONG WINAPI SeekInner_Release(IUnknown * iface) {
118 PassThruImpl *This = impl_from_IUnknown_inner(iface);
119 ULONG ref = InterlockedDecrement(&This->ref);
120
121 TRACE("(%p)->(): new ref = %d\n", This, ref);
122
123 if (ref == 0)
124 {
125 BaseDispatch_Destroy(&This->baseDispatch);
126 This->time_cs.DebugInfo->Spare[0] = 0;
127 DeleteCriticalSection(&This->time_cs);
128 CoTaskMemFree(This);
129 }
130 return ref;
131 }
132
133 static const IUnknownVtbl IInner_VTable =
134 {
135 SeekInner_QueryInterface,
136 SeekInner_AddRef,
137 SeekInner_Release
138 };
139
140 /* Generic functions for aggregation */
141 static HRESULT SeekOuter_QueryInterface(PassThruImpl *This, REFIID riid, LPVOID *ppv)
142 {
143 if (This->bAggregatable)
144 This->bUnkOuterValid = TRUE;
145
146 if (This->outer_unk)
147 {
148 if (This->bAggregatable)
149 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
150
151 if (IsEqualIID(riid, &IID_IUnknown))
152 {
153 HRESULT hr;
154
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;
160 }
161
162 *ppv = NULL;
163 return E_NOINTERFACE;
164 }
165
166 return IUnknown_QueryInterface((IUnknown *)&(This->IUnknown_inner), riid, ppv);
167 }
168
169 static ULONG SeekOuter_AddRef(PassThruImpl *This)
170 {
171 if (This->outer_unk && This->bUnkOuterValid)
172 return IUnknown_AddRef(This->outer_unk);
173 return IUnknown_AddRef((IUnknown *)&(This->IUnknown_inner));
174 }
175
176 static ULONG SeekOuter_Release(PassThruImpl *This)
177 {
178 if (This->outer_unk && This->bUnkOuterValid)
179 return IUnknown_Release(This->outer_unk);
180 return IUnknown_Release((IUnknown *)&(This->IUnknown_inner));
181 }
182
183 static HRESULT WINAPI SeekingPassThru_QueryInterface(ISeekingPassThru *iface, REFIID riid, LPVOID *ppvObj)
184 {
185 PassThruImpl *This = impl_from_ISeekingPassThru(iface);
186
187 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
188
189 return SeekOuter_QueryInterface(This, riid, ppvObj);
190 }
191
192 static ULONG WINAPI SeekingPassThru_AddRef(ISeekingPassThru *iface)
193 {
194 PassThruImpl *This = impl_from_ISeekingPassThru(iface);
195
196 TRACE("(%p/%p)->()\n", This, iface);
197
198 return SeekOuter_AddRef(This);
199 }
200
201 static ULONG WINAPI SeekingPassThru_Release(ISeekingPassThru *iface)
202 {
203 PassThruImpl *This = impl_from_ISeekingPassThru(iface);
204
205 TRACE("(%p/%p)->()\n", This, iface);
206
207 return SeekOuter_Release(This);
208 }
209
210 static HRESULT WINAPI SeekingPassThru_Init(ISeekingPassThru *iface, BOOL renderer, IPin *pin)
211 {
212 PassThruImpl *This = impl_from_ISeekingPassThru(iface);
213
214 TRACE("(%p/%p)->(%d, %p)\n", This, iface, renderer, pin);
215
216 if (This->pin)
217 FIXME("Re-initializing?\n");
218
219 This->renderer = renderer;
220 This->pin = pin;
221
222 return S_OK;
223 }
224
225 static const ISeekingPassThruVtbl ISeekingPassThru_Vtbl =
226 {
227 SeekingPassThru_QueryInterface,
228 SeekingPassThru_AddRef,
229 SeekingPassThru_Release,
230 SeekingPassThru_Init
231 };
232
233 HRESULT WINAPI CreatePosPassThru(IUnknown* pUnkOuter, BOOL bRenderer, IPin *pPin, IUnknown **ppPassThru)
234 {
235 HRESULT hr;
236 ISeekingPassThru *passthru;
237
238 hr = CoCreateInstance(&CLSID_SeekingPassThru, pUnkOuter, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void**)ppPassThru);
239
240 IUnknown_QueryInterface(*ppPassThru, &IID_ISeekingPassThru, (void**)&passthru);
241 hr = ISeekingPassThru_Init(passthru, bRenderer, pPin);
242 ISeekingPassThru_Release(passthru);
243
244 return hr;
245 }
246
247 HRESULT WINAPI PosPassThru_Construct(IUnknown *pUnkOuter, LPVOID *ppPassThru)
248 {
249 PassThruImpl *fimpl;
250
251 TRACE("(%p,%p)\n", pUnkOuter, ppPassThru);
252
253 *ppPassThru = fimpl = CoTaskMemAlloc(sizeof(*fimpl));
254 if (!fimpl)
255 return E_OUTOFMEMORY;
256
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;
271 }
272
273 static HRESULT WINAPI MediaSeekingPassThru_QueryInterface(IMediaSeeking *iface, REFIID riid, LPVOID *ppvObj)
274 {
275 PassThruImpl *This = impl_from_IMediaSeeking(iface);
276
277 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
278
279 return SeekOuter_QueryInterface(This, riid, ppvObj);
280 }
281
282 static ULONG WINAPI MediaSeekingPassThru_AddRef(IMediaSeeking *iface)
283 {
284 PassThruImpl *This = impl_from_IMediaSeeking(iface);
285
286 TRACE("(%p/%p)->()\n", iface, This);
287
288 return SeekOuter_AddRef(This);
289 }
290
291 static ULONG WINAPI MediaSeekingPassThru_Release(IMediaSeeking *iface)
292 {
293 PassThruImpl *This = impl_from_IMediaSeeking(iface);
294
295 TRACE("(%p/%p)->()\n", iface, This);
296
297 return SeekOuter_Release(This);
298 }
299
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;
312 }
313
314 static HRESULT WINAPI MediaSeekingPassThru_GetCapabilities(IMediaSeeking * iface, DWORD * pCapabilities)
315 {
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);
324 }
325 else
326 return E_NOTIMPL;
327 return hr;
328 }
329
330 static HRESULT WINAPI MediaSeekingPassThru_CheckCapabilities(IMediaSeeking * iface, DWORD * pCapabilities)
331 {
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);
340 }
341 else
342 return E_NOTIMPL;
343 return hr;
344 }
345
346 static HRESULT WINAPI MediaSeekingPassThru_IsFormatSupported(IMediaSeeking * iface, const GUID * pFormat)
347 {
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);
356 }
357 else
358 return E_NOTIMPL;
359 return hr;
360 }
361
362 static HRESULT WINAPI MediaSeekingPassThru_QueryPreferredFormat(IMediaSeeking * iface, GUID * pFormat)
363 {
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);
372 }
373 else
374 return E_NOTIMPL;
375 return hr;
376 }
377
378 static HRESULT WINAPI MediaSeekingPassThru_GetTimeFormat(IMediaSeeking * iface, GUID * pFormat)
379 {
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);
388 }
389 else
390 return E_NOTIMPL;
391 return hr;
392 }
393
394 static HRESULT WINAPI MediaSeekingPassThru_IsUsingTimeFormat(IMediaSeeking * iface, const GUID * pFormat)
395 {
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);
404 }
405 else
406 return E_NOTIMPL;
407 return hr;
408 }
409
410 static HRESULT WINAPI MediaSeekingPassThru_SetTimeFormat(IMediaSeeking * iface, const GUID * pFormat)
411 {
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);
420 }
421 else
422 return E_NOTIMPL;
423 return hr;
424 }
425
426 static HRESULT WINAPI MediaSeekingPassThru_GetDuration(IMediaSeeking * iface, LONGLONG * pDuration)
427 {
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);
436 }
437 else
438 return E_NOTIMPL;
439 return hr;
440 }
441
442 static HRESULT WINAPI MediaSeekingPassThru_GetStopPosition(IMediaSeeking * iface, LONGLONG * pStop)
443 {
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);
452 }
453 else
454 return E_NOTIMPL;
455 return hr;
456 }
457
458 static HRESULT WINAPI MediaSeekingPassThru_GetCurrentPosition(IMediaSeeking * iface, LONGLONG * pCurrent)
459 {
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;
475 }
476 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
477 if (SUCCEEDED(hr)) {
478 hr = IMediaSeeking_GetCurrentPosition(seek, pCurrent);
479 IMediaSeeking_Release(seek);
480 }
481 else
482 return E_NOTIMPL;
483 return hr;
484 }
485
486 static HRESULT WINAPI MediaSeekingPassThru_ConvertTimeFormat(IMediaSeeking * iface, LONGLONG * pTarget, const GUID * pTargetFormat, LONGLONG Source, const GUID * pSourceFormat)
487 {
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);
496 }
497 else
498 return E_NOTIMPL;
499 return hr;
500 }
501
502 static HRESULT WINAPI MediaSeekingPassThru_SetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, DWORD dwCurrentFlags, LONGLONG * pStop, DWORD dwStopFlags)
503 {
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;
515 }
516
517 static HRESULT WINAPI MediaSeekingPassThru_GetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, LONGLONG * pStop)
518 {
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);
527 }
528 else
529 return E_NOTIMPL;
530 return hr;
531 }
532
533 static HRESULT WINAPI MediaSeekingPassThru_GetAvailable(IMediaSeeking * iface, LONGLONG * pEarliest, LONGLONG * pLatest)
534 {
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);
543 }
544 else
545 return E_NOTIMPL;
546 return hr;
547 }
548
549 static HRESULT WINAPI MediaSeekingPassThru_SetRate(IMediaSeeking * iface, double dRate)
550 {
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);
559 }
560 else
561 return E_NOTIMPL;
562 return hr;
563 }
564
565 static HRESULT WINAPI MediaSeekingPassThru_GetRate(IMediaSeeking * iface, double * dRate)
566 {
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);
575 }
576 else
577 return E_NOTIMPL;
578 return hr;
579 }
580
581 static HRESULT WINAPI MediaSeekingPassThru_GetPreroll(IMediaSeeking * iface, LONGLONG * pPreroll)
582 {
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);
591 }
592 else
593 return E_NOTIMPL;
594 return hr;
595 }
596
597 HRESULT WINAPI RendererPosPassThru_RegisterMediaTime(IUnknown *iface, REFERENCE_TIME start)
598 {
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;
605 }
606
607 HRESULT WINAPI RendererPosPassThru_ResetMediaTime(IUnknown *iface)
608 {
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;
614 }
615
616 HRESULT WINAPI RendererPosPassThru_EOS(IUnknown *iface)
617 {
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;
630 }
631
632 static const IMediaSeekingVtbl IMediaSeekingPassThru_Vtbl =
633 {
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
654 };
655
656 static HRESULT WINAPI MediaPositionPassThru_QueryInterface(IMediaPosition *iface, REFIID riid, LPVOID *ppvObj)
657 {
658 PassThruImpl *This = impl_from_IMediaPosition(iface);
659
660 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
661
662 return SeekOuter_QueryInterface(This, riid, ppvObj);
663 }
664
665 static ULONG WINAPI MediaPositionPassThru_AddRef(IMediaPosition *iface)
666 {
667 PassThruImpl *This = impl_from_IMediaPosition(iface);
668
669 TRACE("(%p/%p)->()\n", iface, This);
670
671 return SeekOuter_AddRef(This);
672 }
673
674 static ULONG WINAPI MediaPositionPassThru_Release(IMediaPosition *iface)
675 {
676 PassThruImpl *This = impl_from_IMediaPosition(iface);
677
678 TRACE("(%p/%p)->()\n", iface, This);
679
680 return SeekOuter_Release(This);
681 }
682
683 static HRESULT WINAPI MediaPositionPassThru_GetTypeInfoCount(IMediaPosition *iface, UINT*pctinfo)
684 {
685 PassThruImpl *This = impl_from_IMediaPosition(iface);
686
687 return BaseDispatchImpl_GetTypeInfoCount(&This->baseDispatch, pctinfo);
688 }
689
690 static HRESULT WINAPI MediaPositionPassThru_GetTypeInfo(IMediaPosition *iface, UINT iTInfo, LCID lcid, ITypeInfo**ppTInfo)
691 {
692 PassThruImpl *This = impl_from_IMediaPosition(iface);
693
694 return BaseDispatchImpl_GetTypeInfo(&This->baseDispatch, &IID_NULL, iTInfo, lcid, ppTInfo);
695 }
696
697 static HRESULT WINAPI MediaPositionPassThru_GetIDsOfNames(IMediaPosition *iface, REFIID riid, LPOLESTR*rgszNames, UINT cNames, LCID lcid, DISPID*rgDispId)
698 {
699 PassThruImpl *This = impl_from_IMediaPosition(iface);
700
701 return BaseDispatchImpl_GetIDsOfNames(&This->baseDispatch, riid, rgszNames, cNames, lcid, rgDispId);
702 }
703
704 static HRESULT WINAPI MediaPositionPassThru_Invoke(IMediaPosition *iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS*pDispParams, VARIANT*pVarResult, EXCEPINFO*pExepInfo, UINT*puArgErr)
705 {
706 PassThruImpl *This = impl_from_IMediaPosition(iface);
707 HRESULT hr = S_OK;
708 ITypeInfo *pTypeInfo;
709
710 hr = BaseDispatchImpl_GetTypeInfo(&This->baseDispatch, riid, 1, lcid, &pTypeInfo);
711 if (SUCCEEDED(hr))
712 {
713 hr = ITypeInfo_Invoke(pTypeInfo, &This->IMediaPosition_iface, dispIdMember, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
714 ITypeInfo_Release(pTypeInfo);
715 }
716
717 return hr;
718 }
719
720 static HRESULT WINAPI MediaPositionPassThru_get_Duration(IMediaPosition *iface, REFTIME *plength)
721 {
722 PassThruImpl *This = impl_from_IMediaPosition(iface);
723 IMediaPosition *pos;
724 HRESULT hr;
725
726 TRACE("(%p)\n", plength);
727
728 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
729 if (SUCCEEDED(hr)) {
730 hr = IMediaPosition_get_Duration(pos, plength);
731 IMediaPosition_Release(pos);
732 }
733 else
734 return E_NOTIMPL;
735 return hr;
736 }
737
738 static HRESULT WINAPI MediaPositionPassThru_put_CurrentPosition(IMediaPosition *iface, REFTIME llTime)
739 {
740 PassThruImpl *This = impl_from_IMediaPosition(iface);
741 IMediaPosition *pos;
742 HRESULT hr;
743
744 TRACE("(%s)\n", wine_dbgstr_longlong(llTime));
745
746 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
747 if (SUCCEEDED(hr)) {
748 hr = IMediaPosition_put_CurrentPosition(pos, llTime);
749 IMediaPosition_Release(pos);
750 }
751 else
752 return E_NOTIMPL;
753 return hr;
754 }
755
756 static HRESULT WINAPI MediaPositionPassThru_get_CurrentPosition(IMediaPosition *iface, REFTIME *pllTime)
757 {
758 PassThruImpl *This = impl_from_IMediaPosition(iface);
759 IMediaPosition *pos;
760 HRESULT hr;
761
762 TRACE("(%p)\n", pllTime);
763
764 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
765 if (SUCCEEDED(hr)) {
766 hr = IMediaPosition_get_CurrentPosition(pos, pllTime);
767 IMediaPosition_Release(pos);
768 }
769 else
770 return E_NOTIMPL;
771 return hr;
772 }
773
774 static HRESULT WINAPI MediaPositionPassThru_get_StopTime(IMediaPosition *iface, REFTIME *pllTime)
775 {
776 PassThruImpl *This = impl_from_IMediaPosition(iface);
777 IMediaPosition *pos;
778 HRESULT hr;
779
780 TRACE("(%p)\n", pllTime);
781
782 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
783 if (SUCCEEDED(hr)) {
784 hr = IMediaPosition_get_StopTime(pos, pllTime);
785 IMediaPosition_Release(pos);
786 }
787 else
788 return E_NOTIMPL;
789 return hr;
790 }
791
792 static HRESULT WINAPI MediaPositionPassThru_put_StopTime(IMediaPosition *iface, REFTIME llTime)
793 {
794 PassThruImpl *This = impl_from_IMediaPosition(iface);
795 IMediaPosition *pos;
796 HRESULT hr;
797
798 TRACE("(%s)\n", wine_dbgstr_longlong(llTime));
799
800 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
801 if (SUCCEEDED(hr)) {
802 hr = IMediaPosition_put_StopTime(pos, llTime);
803 IMediaPosition_Release(pos);
804 }
805 else
806 return E_NOTIMPL;
807 return hr;
808 }
809
810 static HRESULT WINAPI MediaPositionPassThru_get_PrerollTime(IMediaPosition *iface, REFTIME *pllTime)
811 {
812 PassThruImpl *This = impl_from_IMediaPosition(iface);
813 IMediaPosition *pos;
814 HRESULT hr;
815
816 TRACE("(%p)\n", pllTime);
817
818 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
819 if (SUCCEEDED(hr)) {
820 hr = IMediaPosition_get_PrerollTime(pos, pllTime);
821 IMediaPosition_Release(pos);
822 }
823 else
824 return E_NOTIMPL;
825 return hr;
826 }
827
828 static HRESULT WINAPI MediaPositionPassThru_put_PrerollTime(IMediaPosition *iface, REFTIME llTime)
829 {
830 PassThruImpl *This = impl_from_IMediaPosition(iface);
831 IMediaPosition *pos;
832 HRESULT hr;
833
834 TRACE("(%s)\n", wine_dbgstr_longlong(llTime));
835
836 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
837 if (SUCCEEDED(hr)) {
838 hr = IMediaPosition_put_PrerollTime(pos, llTime);
839 IMediaPosition_Release(pos);
840 }
841 else
842 return E_NOTIMPL;
843 return hr;
844 }
845
846 static HRESULT WINAPI MediaPositionPassThru_put_Rate(IMediaPosition *iface, double dRate)
847 {
848 PassThruImpl *This = impl_from_IMediaPosition(iface);
849 IMediaPosition *pos;
850 HRESULT hr;
851
852 TRACE("(%f)\n", dRate);
853
854 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
855 if (SUCCEEDED(hr)) {
856 hr = IMediaPosition_put_Rate(pos, dRate);
857 IMediaPosition_Release(pos);
858 }
859 else
860 return E_NOTIMPL;
861 return hr;
862 }
863
864 static HRESULT WINAPI MediaPositionPassThru_get_Rate(IMediaPosition *iface, double *pdRate)
865 {
866 PassThruImpl *This = impl_from_IMediaPosition(iface);
867 IMediaPosition *pos;
868 HRESULT hr;
869
870 TRACE("(%p)\n", pdRate);
871
872 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
873 if (SUCCEEDED(hr)) {
874 hr = IMediaPosition_get_Rate(pos, pdRate);
875 IMediaPosition_Release(pos);
876 }
877 else
878 return E_NOTIMPL;
879 return hr;
880 }
881
882 static HRESULT WINAPI MediaPositionPassThru_CanSeekForward(IMediaPosition *iface, LONG *pCanSeekForward)
883 {
884 PassThruImpl *This = impl_from_IMediaPosition(iface);
885 IMediaPosition *pos;
886 HRESULT hr;
887
888 TRACE("(%p)\n", pCanSeekForward);
889
890 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
891 if (SUCCEEDED(hr)) {
892 hr = IMediaPosition_CanSeekForward(pos, pCanSeekForward);
893 IMediaPosition_Release(pos);
894 }
895 else
896 return E_NOTIMPL;
897 return hr;
898 }
899
900 static HRESULT WINAPI MediaPositionPassThru_CanSeekBackward(IMediaPosition *iface, LONG *pCanSeekBackward)
901 {
902 PassThruImpl *This = impl_from_IMediaPosition(iface);
903 IMediaPosition *pos;
904 HRESULT hr;
905
906 TRACE("(%p)\n", pCanSeekBackward);
907
908 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
909 if (SUCCEEDED(hr)) {
910 hr = IMediaPosition_CanSeekBackward(pos, pCanSeekBackward);
911 IMediaPosition_Release(pos);
912 }
913 else
914 return E_NOTIMPL;
915 return hr;
916 }
917
918 static const IMediaPositionVtbl IMediaPositionPassThru_Vtbl =
919 {
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
938 };