[STRMBASE]
[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 #include "strmbase_private.h"
24
25 static const IMediaSeekingVtbl IMediaSeekingPassThru_Vtbl;
26 static const IMediaPositionVtbl IMediaPositionPassThru_Vtbl;
27
28 typedef struct PassThruImpl {
29 IUnknown IUnknown_inner;
30 ISeekingPassThru ISeekingPassThru_iface;
31 IMediaSeeking IMediaSeeking_iface;
32 IMediaPosition IMediaPosition_iface;
33 BaseDispatch baseDispatch;
34
35 LONG ref;
36 IUnknown * outer_unk;
37 IPin * pin;
38 BOOL bUnkOuterValid;
39 BOOL bAggregatable;
40 BOOL renderer;
41 CRITICAL_SECTION time_cs;
42 BOOL timevalid;
43 REFERENCE_TIME time_earliest;
44 } PassThruImpl;
45
46 static inline PassThruImpl *impl_from_IUnknown_inner(IUnknown *iface)
47 {
48 return CONTAINING_RECORD(iface, PassThruImpl, IUnknown_inner);
49 }
50
51 static inline PassThruImpl *impl_from_ISeekingPassThru(ISeekingPassThru *iface)
52 {
53 return CONTAINING_RECORD(iface, PassThruImpl, ISeekingPassThru_iface);
54 }
55
56 static inline PassThruImpl *impl_from_IMediaSeeking(IMediaSeeking *iface)
57 {
58 return CONTAINING_RECORD(iface, PassThruImpl, IMediaSeeking_iface);
59 }
60
61 static inline PassThruImpl *impl_from_IMediaPosition(IMediaPosition *iface)
62 {
63 return CONTAINING_RECORD(iface, PassThruImpl, IMediaPosition_iface);
64 }
65
66 static HRESULT WINAPI SeekInner_QueryInterface(IUnknown * iface,
67 REFIID riid,
68 LPVOID *ppvObj) {
69 PassThruImpl *This = impl_from_IUnknown_inner(iface);
70 TRACE("(%p)->(%s (%p), %p)\n", This, debugstr_guid(riid), riid, ppvObj);
71
72 if (This->bAggregatable)
73 This->bUnkOuterValid = TRUE;
74
75 if (IsEqualGUID(&IID_IUnknown, riid))
76 {
77 *ppvObj = &(This->IUnknown_inner);
78 TRACE(" returning IUnknown interface (%p)\n", *ppvObj);
79 } else if (IsEqualGUID(&IID_ISeekingPassThru, riid)) {
80 *ppvObj = &(This->ISeekingPassThru_iface);
81 TRACE(" returning ISeekingPassThru interface (%p)\n", *ppvObj);
82 } else if (IsEqualGUID(&IID_IMediaSeeking, riid)) {
83 *ppvObj = &(This->IMediaSeeking_iface);
84 TRACE(" returning IMediaSeeking interface (%p)\n", *ppvObj);
85 } else if (IsEqualGUID(&IID_IMediaPosition, riid)) {
86 *ppvObj = &(This->IMediaPosition_iface);
87 TRACE(" returning IMediaPosition interface (%p)\n", *ppvObj);
88 } else {
89 *ppvObj = NULL;
90 FIXME("unknown interface %s\n", debugstr_guid(riid));
91 return E_NOINTERFACE;
92 }
93
94 IUnknown_AddRef((IUnknown *)(*ppvObj));
95 return S_OK;
96 }
97
98 static ULONG WINAPI SeekInner_AddRef(IUnknown * iface) {
99 PassThruImpl *This = impl_from_IUnknown_inner(iface);
100 ULONG ref = InterlockedIncrement(&This->ref);
101
102 TRACE("(%p)->(): new ref = %d\n", This, ref);
103
104 return ref;
105 }
106
107 static ULONG WINAPI SeekInner_Release(IUnknown * iface) {
108 PassThruImpl *This = impl_from_IUnknown_inner(iface);
109 ULONG ref = InterlockedDecrement(&This->ref);
110
111 TRACE("(%p)->(): new ref = %d\n", This, ref);
112
113 if (ref == 0)
114 {
115 BaseDispatch_Destroy(&This->baseDispatch);
116 This->time_cs.DebugInfo->Spare[0] = 0;
117 DeleteCriticalSection(&This->time_cs);
118 CoTaskMemFree(This);
119 }
120 return ref;
121 }
122
123 static const IUnknownVtbl IInner_VTable =
124 {
125 SeekInner_QueryInterface,
126 SeekInner_AddRef,
127 SeekInner_Release
128 };
129
130 /* Generic functions for aggregation */
131 static HRESULT SeekOuter_QueryInterface(PassThruImpl *This, REFIID riid, LPVOID *ppv)
132 {
133 if (This->bAggregatable)
134 This->bUnkOuterValid = TRUE;
135
136 if (This->outer_unk)
137 {
138 if (This->bAggregatable)
139 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
140
141 if (IsEqualIID(riid, &IID_IUnknown))
142 {
143 HRESULT hr;
144
145 IUnknown_AddRef((IUnknown *)&(This->IUnknown_inner));
146 hr = IUnknown_QueryInterface((IUnknown *)&(This->IUnknown_inner), riid, ppv);
147 IUnknown_Release((IUnknown *)&(This->IUnknown_inner));
148 This->bAggregatable = TRUE;
149 return hr;
150 }
151
152 *ppv = NULL;
153 return E_NOINTERFACE;
154 }
155
156 return IUnknown_QueryInterface((IUnknown *)&(This->IUnknown_inner), riid, ppv);
157 }
158
159 static ULONG SeekOuter_AddRef(PassThruImpl *This)
160 {
161 if (This->outer_unk && This->bUnkOuterValid)
162 return IUnknown_AddRef(This->outer_unk);
163 return IUnknown_AddRef((IUnknown *)&(This->IUnknown_inner));
164 }
165
166 static ULONG SeekOuter_Release(PassThruImpl *This)
167 {
168 if (This->outer_unk && This->bUnkOuterValid)
169 return IUnknown_Release(This->outer_unk);
170 return IUnknown_Release((IUnknown *)&(This->IUnknown_inner));
171 }
172
173 static HRESULT WINAPI SeekingPassThru_QueryInterface(ISeekingPassThru *iface, REFIID riid, LPVOID *ppvObj)
174 {
175 PassThruImpl *This = impl_from_ISeekingPassThru(iface);
176
177 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
178
179 return SeekOuter_QueryInterface(This, riid, ppvObj);
180 }
181
182 static ULONG WINAPI SeekingPassThru_AddRef(ISeekingPassThru *iface)
183 {
184 PassThruImpl *This = impl_from_ISeekingPassThru(iface);
185
186 TRACE("(%p/%p)->()\n", This, iface);
187
188 return SeekOuter_AddRef(This);
189 }
190
191 static ULONG WINAPI SeekingPassThru_Release(ISeekingPassThru *iface)
192 {
193 PassThruImpl *This = impl_from_ISeekingPassThru(iface);
194
195 TRACE("(%p/%p)->()\n", This, iface);
196
197 return SeekOuter_Release(This);
198 }
199
200 static HRESULT WINAPI SeekingPassThru_Init(ISeekingPassThru *iface, BOOL renderer, IPin *pin)
201 {
202 PassThruImpl *This = impl_from_ISeekingPassThru(iface);
203
204 TRACE("(%p/%p)->(%d, %p)\n", This, iface, renderer, pin);
205
206 if (This->pin)
207 FIXME("Re-initializing?\n");
208
209 This->renderer = renderer;
210 This->pin = pin;
211
212 return S_OK;
213 }
214
215 static const ISeekingPassThruVtbl ISeekingPassThru_Vtbl =
216 {
217 SeekingPassThru_QueryInterface,
218 SeekingPassThru_AddRef,
219 SeekingPassThru_Release,
220 SeekingPassThru_Init
221 };
222
223 HRESULT WINAPI CreatePosPassThru(IUnknown* pUnkOuter, BOOL bRenderer, IPin *pPin, IUnknown **ppPassThru)
224 {
225 HRESULT hr;
226 ISeekingPassThru *passthru;
227
228 hr = CoCreateInstance(&CLSID_SeekingPassThru, pUnkOuter, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void**)ppPassThru);
229
230 IUnknown_QueryInterface(*ppPassThru, &IID_ISeekingPassThru, (void**)&passthru);
231 hr = ISeekingPassThru_Init(passthru, bRenderer, pPin);
232 ISeekingPassThru_Release(passthru);
233
234 return hr;
235 }
236
237 HRESULT WINAPI PosPassThru_Construct(IUnknown *pUnkOuter, LPVOID *ppPassThru)
238 {
239 PassThruImpl *fimpl;
240
241 TRACE("(%p,%p)\n", pUnkOuter, ppPassThru);
242
243 *ppPassThru = fimpl = CoTaskMemAlloc(sizeof(*fimpl));
244 if (!fimpl)
245 return E_OUTOFMEMORY;
246
247 fimpl->outer_unk = pUnkOuter;
248 fimpl->bUnkOuterValid = FALSE;
249 fimpl->bAggregatable = FALSE;
250 fimpl->IUnknown_inner.lpVtbl = &IInner_VTable;
251 fimpl->ISeekingPassThru_iface.lpVtbl = &ISeekingPassThru_Vtbl;
252 fimpl->IMediaSeeking_iface.lpVtbl = &IMediaSeekingPassThru_Vtbl;
253 fimpl->IMediaPosition_iface.lpVtbl = &IMediaPositionPassThru_Vtbl;
254 fimpl->ref = 1;
255 fimpl->pin = NULL;
256 fimpl->timevalid = 0;
257 InitializeCriticalSection(&fimpl->time_cs);
258 fimpl->time_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": PassThruImpl.time_cs");
259 BaseDispatch_Init(&fimpl->baseDispatch, &IID_IMediaPosition);
260 return S_OK;
261 }
262
263 static HRESULT WINAPI MediaSeekingPassThru_QueryInterface(IMediaSeeking *iface, REFIID riid, LPVOID *ppvObj)
264 {
265 PassThruImpl *This = impl_from_IMediaSeeking(iface);
266
267 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
268
269 return SeekOuter_QueryInterface(This, riid, ppvObj);
270 }
271
272 static ULONG WINAPI MediaSeekingPassThru_AddRef(IMediaSeeking *iface)
273 {
274 PassThruImpl *This = impl_from_IMediaSeeking(iface);
275
276 TRACE("(%p/%p)->()\n", iface, This);
277
278 return SeekOuter_AddRef(This);
279 }
280
281 static ULONG WINAPI MediaSeekingPassThru_Release(IMediaSeeking *iface)
282 {
283 PassThruImpl *This = impl_from_IMediaSeeking(iface);
284
285 TRACE("(%p/%p)->()\n", iface, This);
286
287 return SeekOuter_Release(This);
288 }
289
290 static HRESULT get_connected(PassThruImpl *This, REFIID riid, LPVOID *ppvObj) {
291 HRESULT hr;
292 IPin *pin;
293 *ppvObj = NULL;
294 hr = IPin_ConnectedTo(This->pin, &pin);
295 if (FAILED(hr))
296 return VFW_E_NOT_CONNECTED;
297 hr = IPin_QueryInterface(pin, riid, ppvObj);
298 IPin_Release(pin);
299 if (FAILED(hr))
300 hr = E_NOTIMPL;
301 return hr;
302 }
303
304 static HRESULT WINAPI MediaSeekingPassThru_GetCapabilities(IMediaSeeking * iface, DWORD * pCapabilities)
305 {
306 PassThruImpl *This = impl_from_IMediaSeeking(iface);
307 IMediaSeeking *seek;
308 HRESULT hr;
309 TRACE("(%p/%p)->(%p)\n", iface, This, pCapabilities);
310 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
311 if (SUCCEEDED(hr)) {
312 hr = IMediaSeeking_GetCapabilities(seek, pCapabilities);
313 IMediaSeeking_Release(seek);
314 }
315 else
316 return E_NOTIMPL;
317 return hr;
318 }
319
320 static HRESULT WINAPI MediaSeekingPassThru_CheckCapabilities(IMediaSeeking * iface, DWORD * pCapabilities)
321 {
322 PassThruImpl *This = impl_from_IMediaSeeking(iface);
323 IMediaSeeking *seek;
324 HRESULT hr;
325 TRACE("(%p/%p)->(%p)\n", iface, This, pCapabilities);
326 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
327 if (SUCCEEDED(hr)) {
328 hr = IMediaSeeking_CheckCapabilities(seek, pCapabilities);
329 IMediaSeeking_Release(seek);
330 }
331 else
332 return E_NOTIMPL;
333 return hr;
334 }
335
336 static HRESULT WINAPI MediaSeekingPassThru_IsFormatSupported(IMediaSeeking * iface, const GUID * pFormat)
337 {
338 PassThruImpl *This = impl_from_IMediaSeeking(iface);
339 IMediaSeeking *seek;
340 HRESULT hr;
341 TRACE("(%p/%p)->(%s)\n", iface, This, debugstr_guid(pFormat));
342 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
343 if (SUCCEEDED(hr)) {
344 hr = IMediaSeeking_IsFormatSupported(seek, pFormat);
345 IMediaSeeking_Release(seek);
346 }
347 else
348 return E_NOTIMPL;
349 return hr;
350 }
351
352 static HRESULT WINAPI MediaSeekingPassThru_QueryPreferredFormat(IMediaSeeking * iface, GUID * pFormat)
353 {
354 PassThruImpl *This = impl_from_IMediaSeeking(iface);
355 IMediaSeeking *seek;
356 HRESULT hr;
357 TRACE("(%p/%p)->(%p)\n", iface, This, pFormat);
358 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
359 if (SUCCEEDED(hr)) {
360 hr = IMediaSeeking_QueryPreferredFormat(seek, pFormat);
361 IMediaSeeking_Release(seek);
362 }
363 else
364 return E_NOTIMPL;
365 return hr;
366 }
367
368 static HRESULT WINAPI MediaSeekingPassThru_GetTimeFormat(IMediaSeeking * iface, GUID * pFormat)
369 {
370 PassThruImpl *This = impl_from_IMediaSeeking(iface);
371 IMediaSeeking *seek;
372 HRESULT hr;
373 TRACE("(%p/%p)->(%p)\n", iface, This, pFormat);
374 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
375 if (SUCCEEDED(hr)) {
376 hr = IMediaSeeking_GetTimeFormat(seek, pFormat);
377 IMediaSeeking_Release(seek);
378 }
379 else
380 return E_NOTIMPL;
381 return hr;
382 }
383
384 static HRESULT WINAPI MediaSeekingPassThru_IsUsingTimeFormat(IMediaSeeking * iface, const GUID * pFormat)
385 {
386 PassThruImpl *This = impl_from_IMediaSeeking(iface);
387 IMediaSeeking *seek;
388 HRESULT hr;
389 TRACE("(%p/%p)->(%s)\n", iface, This, debugstr_guid(pFormat));
390 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
391 if (SUCCEEDED(hr)) {
392 hr = IMediaSeeking_IsUsingTimeFormat(seek, pFormat);
393 IMediaSeeking_Release(seek);
394 }
395 else
396 return E_NOTIMPL;
397 return hr;
398 }
399
400 static HRESULT WINAPI MediaSeekingPassThru_SetTimeFormat(IMediaSeeking * iface, const GUID * pFormat)
401 {
402 PassThruImpl *This = impl_from_IMediaSeeking(iface);
403 IMediaSeeking *seek;
404 HRESULT hr;
405 TRACE("(%p/%p)->(%s)\n", iface, This, debugstr_guid(pFormat));
406 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
407 if (SUCCEEDED(hr)) {
408 hr = IMediaSeeking_SetTimeFormat(seek, pFormat);
409 IMediaSeeking_Release(seek);
410 }
411 else
412 return E_NOTIMPL;
413 return hr;
414 }
415
416 static HRESULT WINAPI MediaSeekingPassThru_GetDuration(IMediaSeeking * iface, LONGLONG * pDuration)
417 {
418 PassThruImpl *This = impl_from_IMediaSeeking(iface);
419 IMediaSeeking *seek;
420 HRESULT hr;
421 TRACE("(%p/%p)->(%p)\n", iface, This, pDuration);
422 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
423 if (SUCCEEDED(hr)) {
424 hr = IMediaSeeking_GetDuration(seek, pDuration);
425 IMediaSeeking_Release(seek);
426 }
427 else
428 return E_NOTIMPL;
429 return hr;
430 }
431
432 static HRESULT WINAPI MediaSeekingPassThru_GetStopPosition(IMediaSeeking * iface, LONGLONG * pStop)
433 {
434 PassThruImpl *This = impl_from_IMediaSeeking(iface);
435 IMediaSeeking *seek;
436 HRESULT hr;
437 TRACE("(%p/%p)->(%p)\n", iface, This, pStop);
438 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
439 if (SUCCEEDED(hr)) {
440 hr = IMediaSeeking_GetStopPosition(seek, pStop);
441 IMediaSeeking_Release(seek);
442 }
443 else
444 return E_NOTIMPL;
445 return hr;
446 }
447
448 static HRESULT WINAPI MediaSeekingPassThru_GetCurrentPosition(IMediaSeeking * iface, LONGLONG * pCurrent)
449 {
450 PassThruImpl *This = impl_from_IMediaSeeking(iface);
451 IMediaSeeking *seek;
452 HRESULT hr = S_OK;
453 TRACE("(%p/%p)->(%p)\n", iface, This, pCurrent);
454 if (!pCurrent)
455 return E_POINTER;
456 EnterCriticalSection(&This->time_cs);
457 if (This->timevalid)
458 *pCurrent = This->time_earliest;
459 else
460 hr = E_FAIL;
461 LeaveCriticalSection(&This->time_cs);
462 if (SUCCEEDED(hr)) {
463 hr = IMediaSeeking_ConvertTimeFormat(iface, pCurrent, NULL, *pCurrent, &TIME_FORMAT_MEDIA_TIME);
464 return hr;
465 }
466 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
467 if (SUCCEEDED(hr)) {
468 hr = IMediaSeeking_GetCurrentPosition(seek, pCurrent);
469 IMediaSeeking_Release(seek);
470 }
471 else
472 return E_NOTIMPL;
473 return hr;
474 }
475
476 static HRESULT WINAPI MediaSeekingPassThru_ConvertTimeFormat(IMediaSeeking * iface, LONGLONG * pTarget, const GUID * pTargetFormat, LONGLONG Source, const GUID * pSourceFormat)
477 {
478 PassThruImpl *This = impl_from_IMediaSeeking(iface);
479 IMediaSeeking *seek;
480 HRESULT hr;
481 TRACE("(%p/%p)->(%p,%s,%x%08x,%s)\n", iface, This, pTarget, debugstr_guid(pTargetFormat), (DWORD)(Source>>32), (DWORD)Source, debugstr_guid(pSourceFormat));
482 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
483 if (SUCCEEDED(hr)) {
484 hr = IMediaSeeking_ConvertTimeFormat(seek, pTarget, pTargetFormat, Source, pSourceFormat);
485 IMediaSeeking_Release(seek);
486 }
487 else
488 return E_NOTIMPL;
489 return hr;
490 }
491
492 static HRESULT WINAPI MediaSeekingPassThru_SetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, DWORD dwCurrentFlags, LONGLONG * pStop, DWORD dwStopFlags)
493 {
494 PassThruImpl *This = impl_from_IMediaSeeking(iface);
495 IMediaSeeking *seek;
496 HRESULT hr;
497 TRACE("(%p/%p)->(%p,%x,%p,%x)\n", iface, This, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
498 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
499 if (SUCCEEDED(hr)) {
500 hr = IMediaSeeking_SetPositions(seek, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
501 IMediaSeeking_Release(seek);
502 } else if (hr == VFW_E_NOT_CONNECTED)
503 hr = S_OK;
504 return hr;
505 }
506
507 static HRESULT WINAPI MediaSeekingPassThru_GetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, LONGLONG * pStop)
508 {
509 PassThruImpl *This = impl_from_IMediaSeeking(iface);
510 IMediaSeeking *seek;
511 HRESULT hr;
512 TRACE("(%p/%p)->(%p, %p)\n", iface, This, pCurrent, pStop);
513 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
514 if (SUCCEEDED(hr)) {
515 hr = IMediaSeeking_GetPositions(seek, pCurrent, pStop);
516 IMediaSeeking_Release(seek);
517 }
518 else
519 return E_NOTIMPL;
520 return hr;
521 }
522
523 static HRESULT WINAPI MediaSeekingPassThru_GetAvailable(IMediaSeeking * iface, LONGLONG * pEarliest, LONGLONG * pLatest)
524 {
525 PassThruImpl *This = impl_from_IMediaSeeking(iface);
526 IMediaSeeking *seek;
527 HRESULT hr;
528 TRACE("(%p/%p)->(%p,%p)\n", iface, This, pEarliest, pLatest);
529 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
530 if (SUCCEEDED(hr)) {
531 hr = IMediaSeeking_GetAvailable(seek, pEarliest, pLatest);
532 IMediaSeeking_Release(seek);
533 }
534 else
535 return E_NOTIMPL;
536 return hr;
537 }
538
539 static HRESULT WINAPI MediaSeekingPassThru_SetRate(IMediaSeeking * iface, double dRate)
540 {
541 PassThruImpl *This = impl_from_IMediaSeeking(iface);
542 IMediaSeeking *seek;
543 HRESULT hr;
544 TRACE("(%p/%p)->(%e)\n", iface, This, dRate);
545 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
546 if (SUCCEEDED(hr)) {
547 hr = IMediaSeeking_SetRate(seek, dRate);
548 IMediaSeeking_Release(seek);
549 }
550 else
551 return E_NOTIMPL;
552 return hr;
553 }
554
555 static HRESULT WINAPI MediaSeekingPassThru_GetRate(IMediaSeeking * iface, double * dRate)
556 {
557 PassThruImpl *This = impl_from_IMediaSeeking(iface);
558 IMediaSeeking *seek;
559 HRESULT hr;
560 TRACE("(%p/%p)->(%p)\n", iface, This, dRate);
561 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
562 if (SUCCEEDED(hr)) {
563 hr = IMediaSeeking_GetRate(seek, dRate);
564 IMediaSeeking_Release(seek);
565 }
566 else
567 return E_NOTIMPL;
568 return hr;
569 }
570
571 static HRESULT WINAPI MediaSeekingPassThru_GetPreroll(IMediaSeeking * iface, LONGLONG * pPreroll)
572 {
573 PassThruImpl *This = impl_from_IMediaSeeking(iface);
574 IMediaSeeking *seek;
575 HRESULT hr;
576 TRACE("(%p)\n", pPreroll);
577 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
578 if (SUCCEEDED(hr)) {
579 hr = IMediaSeeking_GetPreroll(seek, pPreroll);
580 IMediaSeeking_Release(seek);
581 }
582 else
583 return E_NOTIMPL;
584 return hr;
585 }
586
587 HRESULT WINAPI RendererPosPassThru_RegisterMediaTime(IUnknown *iface, REFERENCE_TIME start)
588 {
589 PassThruImpl *This = impl_from_IUnknown_inner(iface);
590 EnterCriticalSection(&This->time_cs);
591 This->time_earliest = start;
592 This->timevalid = 1;
593 LeaveCriticalSection(&This->time_cs);
594 return S_OK;
595 }
596
597 HRESULT WINAPI RendererPosPassThru_ResetMediaTime(IUnknown *iface)
598 {
599 PassThruImpl *This = impl_from_IUnknown_inner(iface);
600 EnterCriticalSection(&This->time_cs);
601 This->timevalid = 0;
602 LeaveCriticalSection(&This->time_cs);
603 return S_OK;
604 }
605
606 HRESULT WINAPI RendererPosPassThru_EOS(IUnknown *iface)
607 {
608 PassThruImpl *This = impl_from_IUnknown_inner(iface);
609 REFERENCE_TIME time;
610 HRESULT hr;
611 hr = IMediaSeeking_GetStopPosition(&This->IMediaSeeking_iface, &time);
612 EnterCriticalSection(&This->time_cs);
613 if (SUCCEEDED(hr)) {
614 This->timevalid = 1;
615 This->time_earliest = time;
616 } else
617 This->timevalid = 0;
618 LeaveCriticalSection(&This->time_cs);
619 return hr;
620 }
621
622 static const IMediaSeekingVtbl IMediaSeekingPassThru_Vtbl =
623 {
624 MediaSeekingPassThru_QueryInterface,
625 MediaSeekingPassThru_AddRef,
626 MediaSeekingPassThru_Release,
627 MediaSeekingPassThru_GetCapabilities,
628 MediaSeekingPassThru_CheckCapabilities,
629 MediaSeekingPassThru_IsFormatSupported,
630 MediaSeekingPassThru_QueryPreferredFormat,
631 MediaSeekingPassThru_GetTimeFormat,
632 MediaSeekingPassThru_IsUsingTimeFormat,
633 MediaSeekingPassThru_SetTimeFormat,
634 MediaSeekingPassThru_GetDuration,
635 MediaSeekingPassThru_GetStopPosition,
636 MediaSeekingPassThru_GetCurrentPosition,
637 MediaSeekingPassThru_ConvertTimeFormat,
638 MediaSeekingPassThru_SetPositions,
639 MediaSeekingPassThru_GetPositions,
640 MediaSeekingPassThru_GetAvailable,
641 MediaSeekingPassThru_SetRate,
642 MediaSeekingPassThru_GetRate,
643 MediaSeekingPassThru_GetPreroll
644 };
645
646 static HRESULT WINAPI MediaPositionPassThru_QueryInterface(IMediaPosition *iface, REFIID riid, LPVOID *ppvObj)
647 {
648 PassThruImpl *This = impl_from_IMediaPosition(iface);
649
650 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
651
652 return SeekOuter_QueryInterface(This, riid, ppvObj);
653 }
654
655 static ULONG WINAPI MediaPositionPassThru_AddRef(IMediaPosition *iface)
656 {
657 PassThruImpl *This = impl_from_IMediaPosition(iface);
658
659 TRACE("(%p/%p)->()\n", iface, This);
660
661 return SeekOuter_AddRef(This);
662 }
663
664 static ULONG WINAPI MediaPositionPassThru_Release(IMediaPosition *iface)
665 {
666 PassThruImpl *This = impl_from_IMediaPosition(iface);
667
668 TRACE("(%p/%p)->()\n", iface, This);
669
670 return SeekOuter_Release(This);
671 }
672
673 static HRESULT WINAPI MediaPositionPassThru_GetTypeInfoCount(IMediaPosition *iface, UINT*pctinfo)
674 {
675 PassThruImpl *This = impl_from_IMediaPosition(iface);
676
677 return BaseDispatchImpl_GetTypeInfoCount(&This->baseDispatch, pctinfo);
678 }
679
680 static HRESULT WINAPI MediaPositionPassThru_GetTypeInfo(IMediaPosition *iface, UINT iTInfo, LCID lcid, ITypeInfo**ppTInfo)
681 {
682 PassThruImpl *This = impl_from_IMediaPosition(iface);
683
684 return BaseDispatchImpl_GetTypeInfo(&This->baseDispatch, &IID_NULL, iTInfo, lcid, ppTInfo);
685 }
686
687 static HRESULT WINAPI MediaPositionPassThru_GetIDsOfNames(IMediaPosition *iface, REFIID riid, LPOLESTR*rgszNames, UINT cNames, LCID lcid, DISPID*rgDispId)
688 {
689 PassThruImpl *This = impl_from_IMediaPosition(iface);
690
691 return BaseDispatchImpl_GetIDsOfNames(&This->baseDispatch, riid, rgszNames, cNames, lcid, rgDispId);
692 }
693
694 static HRESULT WINAPI MediaPositionPassThru_Invoke(IMediaPosition *iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS*pDispParams, VARIANT*pVarResult, EXCEPINFO*pExepInfo, UINT*puArgErr)
695 {
696 PassThruImpl *This = impl_from_IMediaPosition(iface);
697 HRESULT hr = S_OK;
698 ITypeInfo *pTypeInfo;
699
700 hr = BaseDispatchImpl_GetTypeInfo(&This->baseDispatch, riid, 1, lcid, &pTypeInfo);
701 if (SUCCEEDED(hr))
702 {
703 hr = ITypeInfo_Invoke(pTypeInfo, &This->IMediaPosition_iface, dispIdMember, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
704 ITypeInfo_Release(pTypeInfo);
705 }
706
707 return hr;
708 }
709
710 static HRESULT WINAPI MediaPositionPassThru_get_Duration(IMediaPosition *iface, REFTIME *plength)
711 {
712 PassThruImpl *This = impl_from_IMediaPosition(iface);
713 IMediaPosition *pos;
714 HRESULT hr;
715
716 TRACE("(%p)\n", plength);
717
718 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
719 if (SUCCEEDED(hr)) {
720 hr = IMediaPosition_get_Duration(pos, plength);
721 IMediaPosition_Release(pos);
722 }
723 else
724 return E_NOTIMPL;
725 return hr;
726 }
727
728 static HRESULT WINAPI MediaPositionPassThru_put_CurrentPosition(IMediaPosition *iface, REFTIME llTime)
729 {
730 PassThruImpl *This = impl_from_IMediaPosition(iface);
731 IMediaPosition *pos;
732 HRESULT hr;
733
734 TRACE("(%s)\n", wine_dbgstr_longlong(llTime));
735
736 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
737 if (SUCCEEDED(hr)) {
738 hr = IMediaPosition_put_CurrentPosition(pos, llTime);
739 IMediaPosition_Release(pos);
740 }
741 else
742 return E_NOTIMPL;
743 return hr;
744 }
745
746 static HRESULT WINAPI MediaPositionPassThru_get_CurrentPosition(IMediaPosition *iface, REFTIME *pllTime)
747 {
748 PassThruImpl *This = impl_from_IMediaPosition(iface);
749 IMediaPosition *pos;
750 HRESULT hr;
751
752 TRACE("(%p)\n", pllTime);
753
754 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
755 if (SUCCEEDED(hr)) {
756 hr = IMediaPosition_get_CurrentPosition(pos, pllTime);
757 IMediaPosition_Release(pos);
758 }
759 else
760 return E_NOTIMPL;
761 return hr;
762 }
763
764 static HRESULT WINAPI MediaPositionPassThru_get_StopTime(IMediaPosition *iface, REFTIME *pllTime)
765 {
766 PassThruImpl *This = impl_from_IMediaPosition(iface);
767 IMediaPosition *pos;
768 HRESULT hr;
769
770 TRACE("(%p)\n", pllTime);
771
772 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
773 if (SUCCEEDED(hr)) {
774 hr = IMediaPosition_get_StopTime(pos, pllTime);
775 IMediaPosition_Release(pos);
776 }
777 else
778 return E_NOTIMPL;
779 return hr;
780 }
781
782 static HRESULT WINAPI MediaPositionPassThru_put_StopTime(IMediaPosition *iface, REFTIME llTime)
783 {
784 PassThruImpl *This = impl_from_IMediaPosition(iface);
785 IMediaPosition *pos;
786 HRESULT hr;
787
788 TRACE("(%s)\n", wine_dbgstr_longlong(llTime));
789
790 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
791 if (SUCCEEDED(hr)) {
792 hr = IMediaPosition_put_StopTime(pos, llTime);
793 IMediaPosition_Release(pos);
794 }
795 else
796 return E_NOTIMPL;
797 return hr;
798 }
799
800 static HRESULT WINAPI MediaPositionPassThru_get_PrerollTime(IMediaPosition *iface, REFTIME *pllTime)
801 {
802 PassThruImpl *This = impl_from_IMediaPosition(iface);
803 IMediaPosition *pos;
804 HRESULT hr;
805
806 TRACE("(%p)\n", pllTime);
807
808 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
809 if (SUCCEEDED(hr)) {
810 hr = IMediaPosition_get_PrerollTime(pos, pllTime);
811 IMediaPosition_Release(pos);
812 }
813 else
814 return E_NOTIMPL;
815 return hr;
816 }
817
818 static HRESULT WINAPI MediaPositionPassThru_put_PrerollTime(IMediaPosition *iface, REFTIME llTime)
819 {
820 PassThruImpl *This = impl_from_IMediaPosition(iface);
821 IMediaPosition *pos;
822 HRESULT hr;
823
824 TRACE("(%s)\n", wine_dbgstr_longlong(llTime));
825
826 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
827 if (SUCCEEDED(hr)) {
828 hr = IMediaPosition_put_PrerollTime(pos, llTime);
829 IMediaPosition_Release(pos);
830 }
831 else
832 return E_NOTIMPL;
833 return hr;
834 }
835
836 static HRESULT WINAPI MediaPositionPassThru_put_Rate(IMediaPosition *iface, double dRate)
837 {
838 PassThruImpl *This = impl_from_IMediaPosition(iface);
839 IMediaPosition *pos;
840 HRESULT hr;
841
842 TRACE("(%f)\n", dRate);
843
844 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
845 if (SUCCEEDED(hr)) {
846 hr = IMediaPosition_put_Rate(pos, dRate);
847 IMediaPosition_Release(pos);
848 }
849 else
850 return E_NOTIMPL;
851 return hr;
852 }
853
854 static HRESULT WINAPI MediaPositionPassThru_get_Rate(IMediaPosition *iface, double *pdRate)
855 {
856 PassThruImpl *This = impl_from_IMediaPosition(iface);
857 IMediaPosition *pos;
858 HRESULT hr;
859
860 TRACE("(%p)\n", pdRate);
861
862 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
863 if (SUCCEEDED(hr)) {
864 hr = IMediaPosition_get_Rate(pos, pdRate);
865 IMediaPosition_Release(pos);
866 }
867 else
868 return E_NOTIMPL;
869 return hr;
870 }
871
872 static HRESULT WINAPI MediaPositionPassThru_CanSeekForward(IMediaPosition *iface, LONG *pCanSeekForward)
873 {
874 PassThruImpl *This = impl_from_IMediaPosition(iface);
875 IMediaPosition *pos;
876 HRESULT hr;
877
878 TRACE("(%p)\n", pCanSeekForward);
879
880 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
881 if (SUCCEEDED(hr)) {
882 hr = IMediaPosition_CanSeekForward(pos, pCanSeekForward);
883 IMediaPosition_Release(pos);
884 }
885 else
886 return E_NOTIMPL;
887 return hr;
888 }
889
890 static HRESULT WINAPI MediaPositionPassThru_CanSeekBackward(IMediaPosition *iface, LONG *pCanSeekBackward)
891 {
892 PassThruImpl *This = impl_from_IMediaPosition(iface);
893 IMediaPosition *pos;
894 HRESULT hr;
895
896 TRACE("(%p)\n", pCanSeekBackward);
897
898 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
899 if (SUCCEEDED(hr)) {
900 hr = IMediaPosition_CanSeekBackward(pos, pCanSeekBackward);
901 IMediaPosition_Release(pos);
902 }
903 else
904 return E_NOTIMPL;
905 return hr;
906 }
907
908 static const IMediaPositionVtbl IMediaPositionPassThru_Vtbl =
909 {
910 MediaPositionPassThru_QueryInterface,
911 MediaPositionPassThru_AddRef,
912 MediaPositionPassThru_Release,
913 MediaPositionPassThru_GetTypeInfoCount,
914 MediaPositionPassThru_GetTypeInfo,
915 MediaPositionPassThru_GetIDsOfNames,
916 MediaPositionPassThru_Invoke,
917 MediaPositionPassThru_get_Duration,
918 MediaPositionPassThru_put_CurrentPosition,
919 MediaPositionPassThru_get_CurrentPosition,
920 MediaPositionPassThru_get_StopTime,
921 MediaPositionPassThru_put_StopTime,
922 MediaPositionPassThru_get_PrerollTime,
923 MediaPositionPassThru_put_PrerollTime,
924 MediaPositionPassThru_put_Rate,
925 MediaPositionPassThru_get_Rate,
926 MediaPositionPassThru_CanSeekForward,
927 MediaPositionPassThru_CanSeekBackward
928 };