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
impl_from_IUnknown_inner(IUnknown * iface)56 static inline PassThruImpl *impl_from_IUnknown_inner(IUnknown *iface)
57 {
58 return CONTAINING_RECORD(iface, PassThruImpl, IUnknown_inner);
59 }
60
impl_from_ISeekingPassThru(ISeekingPassThru * iface)61 static inline PassThruImpl *impl_from_ISeekingPassThru(ISeekingPassThru *iface)
62 {
63 return CONTAINING_RECORD(iface, PassThruImpl, ISeekingPassThru_iface);
64 }
65
impl_from_IMediaSeeking(IMediaSeeking * iface)66 static inline PassThruImpl *impl_from_IMediaSeeking(IMediaSeeking *iface)
67 {
68 return CONTAINING_RECORD(iface, PassThruImpl, IMediaSeeking_iface);
69 }
70
impl_from_IMediaPosition(IMediaPosition * iface)71 static inline PassThruImpl *impl_from_IMediaPosition(IMediaPosition *iface)
72 {
73 return CONTAINING_RECORD(iface, PassThruImpl, IMediaPosition_iface);
74 }
75
SeekInner_QueryInterface(IUnknown * iface,REFIID riid,LPVOID * ppvObj)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);
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
SeekInner_AddRef(IUnknown * iface)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
SeekInner_Release(IUnknown * iface)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 */
SeekOuter_QueryInterface(PassThruImpl * This,REFIID riid,LPVOID * ppv)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(&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;
160 }
161
162 *ppv = NULL;
163 return E_NOINTERFACE;
164 }
165
166 return IUnknown_QueryInterface(&This->IUnknown_inner, riid, ppv);
167 }
168
SeekOuter_AddRef(PassThruImpl * This)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(&This->IUnknown_inner);
174 }
175
SeekOuter_Release(PassThruImpl * This)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(&This->IUnknown_inner);
181 }
182
SeekingPassThru_QueryInterface(ISeekingPassThru * iface,REFIID riid,LPVOID * ppvObj)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)\n", This, iface, debugstr_guid(riid), ppvObj);
188
189 return SeekOuter_QueryInterface(This, riid, ppvObj);
190 }
191
SeekingPassThru_AddRef(ISeekingPassThru * iface)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
SeekingPassThru_Release(ISeekingPassThru * iface)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
SeekingPassThru_Init(ISeekingPassThru * iface,BOOL renderer,IPin * pin)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
CreatePosPassThru(IUnknown * pUnkOuter,BOOL bRenderer,IPin * pPin,IUnknown ** ppPassThru)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 if (FAILED(hr))
240 return hr;
241
242 IUnknown_QueryInterface(*ppPassThru, &IID_ISeekingPassThru, (void**)&passthru);
243 hr = ISeekingPassThru_Init(passthru, bRenderer, pPin);
244 ISeekingPassThru_Release(passthru);
245
246 return hr;
247 }
248
PosPassThru_Construct(IUnknown * pUnkOuter,LPVOID * ppPassThru)249 HRESULT WINAPI PosPassThru_Construct(IUnknown *pUnkOuter, LPVOID *ppPassThru)
250 {
251 PassThruImpl *fimpl;
252
253 TRACE("(%p,%p)\n", pUnkOuter, ppPassThru);
254
255 *ppPassThru = fimpl = CoTaskMemAlloc(sizeof(*fimpl));
256 if (!fimpl)
257 return E_OUTOFMEMORY;
258
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;
273 }
274
MediaSeekingPassThru_QueryInterface(IMediaSeeking * iface,REFIID riid,LPVOID * ppvObj)275 static HRESULT WINAPI MediaSeekingPassThru_QueryInterface(IMediaSeeking *iface, REFIID riid, LPVOID *ppvObj)
276 {
277 PassThruImpl *This = impl_from_IMediaSeeking(iface);
278
279 TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj);
280
281 return SeekOuter_QueryInterface(This, riid, ppvObj);
282 }
283
MediaSeekingPassThru_AddRef(IMediaSeeking * iface)284 static ULONG WINAPI MediaSeekingPassThru_AddRef(IMediaSeeking *iface)
285 {
286 PassThruImpl *This = impl_from_IMediaSeeking(iface);
287
288 TRACE("(%p/%p)->()\n", iface, This);
289
290 return SeekOuter_AddRef(This);
291 }
292
MediaSeekingPassThru_Release(IMediaSeeking * iface)293 static ULONG WINAPI MediaSeekingPassThru_Release(IMediaSeeking *iface)
294 {
295 PassThruImpl *This = impl_from_IMediaSeeking(iface);
296
297 TRACE("(%p/%p)->()\n", iface, This);
298
299 return SeekOuter_Release(This);
300 }
301
get_connected(PassThruImpl * This,REFIID riid,LPVOID * ppvObj)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;
314 }
315
MediaSeekingPassThru_GetCapabilities(IMediaSeeking * iface,DWORD * pCapabilities)316 static HRESULT WINAPI MediaSeekingPassThru_GetCapabilities(IMediaSeeking * iface, DWORD * pCapabilities)
317 {
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);
326 }
327 else
328 return E_NOTIMPL;
329 return hr;
330 }
331
MediaSeekingPassThru_CheckCapabilities(IMediaSeeking * iface,DWORD * pCapabilities)332 static HRESULT WINAPI MediaSeekingPassThru_CheckCapabilities(IMediaSeeking * iface, DWORD * pCapabilities)
333 {
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);
342 }
343 else
344 return E_NOTIMPL;
345 return hr;
346 }
347
MediaSeekingPassThru_IsFormatSupported(IMediaSeeking * iface,const GUID * pFormat)348 static HRESULT WINAPI MediaSeekingPassThru_IsFormatSupported(IMediaSeeking * iface, const GUID * pFormat)
349 {
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);
358 }
359 else
360 return E_NOTIMPL;
361 return hr;
362 }
363
MediaSeekingPassThru_QueryPreferredFormat(IMediaSeeking * iface,GUID * pFormat)364 static HRESULT WINAPI MediaSeekingPassThru_QueryPreferredFormat(IMediaSeeking * iface, GUID * pFormat)
365 {
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);
374 }
375 else
376 return E_NOTIMPL;
377 return hr;
378 }
379
MediaSeekingPassThru_GetTimeFormat(IMediaSeeking * iface,GUID * pFormat)380 static HRESULT WINAPI MediaSeekingPassThru_GetTimeFormat(IMediaSeeking * iface, GUID * pFormat)
381 {
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);
390 }
391 else
392 return E_NOTIMPL;
393 return hr;
394 }
395
MediaSeekingPassThru_IsUsingTimeFormat(IMediaSeeking * iface,const GUID * pFormat)396 static HRESULT WINAPI MediaSeekingPassThru_IsUsingTimeFormat(IMediaSeeking * iface, const GUID * pFormat)
397 {
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);
406 }
407 else
408 return E_NOTIMPL;
409 return hr;
410 }
411
MediaSeekingPassThru_SetTimeFormat(IMediaSeeking * iface,const GUID * pFormat)412 static HRESULT WINAPI MediaSeekingPassThru_SetTimeFormat(IMediaSeeking * iface, const GUID * pFormat)
413 {
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);
422 }
423 else
424 return E_NOTIMPL;
425 return hr;
426 }
427
MediaSeekingPassThru_GetDuration(IMediaSeeking * iface,LONGLONG * pDuration)428 static HRESULT WINAPI MediaSeekingPassThru_GetDuration(IMediaSeeking * iface, LONGLONG * pDuration)
429 {
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);
438 }
439 else
440 return E_NOTIMPL;
441 return hr;
442 }
443
MediaSeekingPassThru_GetStopPosition(IMediaSeeking * iface,LONGLONG * pStop)444 static HRESULT WINAPI MediaSeekingPassThru_GetStopPosition(IMediaSeeking * iface, LONGLONG * pStop)
445 {
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);
454 }
455 else
456 return E_NOTIMPL;
457 return hr;
458 }
459
MediaSeekingPassThru_GetCurrentPosition(IMediaSeeking * iface,LONGLONG * pCurrent)460 static HRESULT WINAPI MediaSeekingPassThru_GetCurrentPosition(IMediaSeeking * iface, LONGLONG * pCurrent)
461 {
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;
477 }
478 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
479 if (SUCCEEDED(hr)) {
480 hr = IMediaSeeking_GetCurrentPosition(seek, pCurrent);
481 IMediaSeeking_Release(seek);
482 }
483 else
484 return E_NOTIMPL;
485 return hr;
486 }
487
MediaSeekingPassThru_ConvertTimeFormat(IMediaSeeking * iface,LONGLONG * pTarget,const GUID * pTargetFormat,LONGLONG Source,const GUID * pSourceFormat)488 static HRESULT WINAPI MediaSeekingPassThru_ConvertTimeFormat(IMediaSeeking * iface, LONGLONG * pTarget, const GUID * pTargetFormat, LONGLONG Source, const GUID * pSourceFormat)
489 {
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);
498 }
499 else
500 return E_NOTIMPL;
501 return hr;
502 }
503
MediaSeekingPassThru_SetPositions(IMediaSeeking * iface,LONGLONG * pCurrent,DWORD dwCurrentFlags,LONGLONG * pStop,DWORD dwStopFlags)504 static HRESULT WINAPI MediaSeekingPassThru_SetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, DWORD dwCurrentFlags, LONGLONG * pStop, DWORD dwStopFlags)
505 {
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;
517 }
518
MediaSeekingPassThru_GetPositions(IMediaSeeking * iface,LONGLONG * pCurrent,LONGLONG * pStop)519 static HRESULT WINAPI MediaSeekingPassThru_GetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, LONGLONG * pStop)
520 {
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);
529 } else if (hr == VFW_E_NOT_CONNECTED) {
530 *pCurrent = 0;
531 *pStop = 0;
532 hr = S_OK;
533 }
534 return hr;
535 }
536
MediaSeekingPassThru_GetAvailable(IMediaSeeking * iface,LONGLONG * pEarliest,LONGLONG * pLatest)537 static HRESULT WINAPI MediaSeekingPassThru_GetAvailable(IMediaSeeking * iface, LONGLONG * pEarliest, LONGLONG * pLatest)
538 {
539 PassThruImpl *This = impl_from_IMediaSeeking(iface);
540 IMediaSeeking *seek;
541 HRESULT hr;
542 TRACE("(%p/%p)->(%p,%p)\n", iface, This, pEarliest, pLatest);
543 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
544 if (SUCCEEDED(hr)) {
545 hr = IMediaSeeking_GetAvailable(seek, pEarliest, pLatest);
546 IMediaSeeking_Release(seek);
547 }
548 else
549 return E_NOTIMPL;
550 return hr;
551 }
552
MediaSeekingPassThru_SetRate(IMediaSeeking * iface,double dRate)553 static HRESULT WINAPI MediaSeekingPassThru_SetRate(IMediaSeeking * iface, double dRate)
554 {
555 PassThruImpl *This = impl_from_IMediaSeeking(iface);
556 IMediaSeeking *seek;
557 HRESULT hr;
558 TRACE("(%p/%p)->(%e)\n", iface, This, dRate);
559 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
560 if (SUCCEEDED(hr)) {
561 hr = IMediaSeeking_SetRate(seek, dRate);
562 IMediaSeeking_Release(seek);
563 }
564 else
565 return E_NOTIMPL;
566 return hr;
567 }
568
MediaSeekingPassThru_GetRate(IMediaSeeking * iface,double * dRate)569 static HRESULT WINAPI MediaSeekingPassThru_GetRate(IMediaSeeking * iface, double * dRate)
570 {
571 PassThruImpl *This = impl_from_IMediaSeeking(iface);
572 IMediaSeeking *seek;
573 HRESULT hr;
574 TRACE("(%p/%p)->(%p)\n", iface, This, dRate);
575 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
576 if (SUCCEEDED(hr)) {
577 hr = IMediaSeeking_GetRate(seek, dRate);
578 IMediaSeeking_Release(seek);
579 }
580 else
581 return E_NOTIMPL;
582 return hr;
583 }
584
MediaSeekingPassThru_GetPreroll(IMediaSeeking * iface,LONGLONG * pPreroll)585 static HRESULT WINAPI MediaSeekingPassThru_GetPreroll(IMediaSeeking * iface, LONGLONG * pPreroll)
586 {
587 PassThruImpl *This = impl_from_IMediaSeeking(iface);
588 IMediaSeeking *seek;
589 HRESULT hr;
590 TRACE("(%p)\n", pPreroll);
591 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek);
592 if (SUCCEEDED(hr)) {
593 hr = IMediaSeeking_GetPreroll(seek, pPreroll);
594 IMediaSeeking_Release(seek);
595 }
596 else
597 return E_NOTIMPL;
598 return hr;
599 }
600
RendererPosPassThru_RegisterMediaTime(IUnknown * iface,REFERENCE_TIME start)601 HRESULT WINAPI RendererPosPassThru_RegisterMediaTime(IUnknown *iface, REFERENCE_TIME start)
602 {
603 PassThruImpl *This = impl_from_IUnknown_inner(iface);
604 EnterCriticalSection(&This->time_cs);
605 This->time_earliest = start;
606 This->timevalid = TRUE;
607 LeaveCriticalSection(&This->time_cs);
608 return S_OK;
609 }
610
RendererPosPassThru_ResetMediaTime(IUnknown * iface)611 HRESULT WINAPI RendererPosPassThru_ResetMediaTime(IUnknown *iface)
612 {
613 PassThruImpl *This = impl_from_IUnknown_inner(iface);
614 EnterCriticalSection(&This->time_cs);
615 This->timevalid = FALSE;
616 LeaveCriticalSection(&This->time_cs);
617 return S_OK;
618 }
619
RendererPosPassThru_EOS(IUnknown * iface)620 HRESULT WINAPI RendererPosPassThru_EOS(IUnknown *iface)
621 {
622 PassThruImpl *This = impl_from_IUnknown_inner(iface);
623 REFERENCE_TIME time;
624 HRESULT hr;
625 hr = IMediaSeeking_GetStopPosition(&This->IMediaSeeking_iface, &time);
626 EnterCriticalSection(&This->time_cs);
627 if (SUCCEEDED(hr)) {
628 This->timevalid = TRUE;
629 This->time_earliest = time;
630 } else
631 This->timevalid = FALSE;
632 LeaveCriticalSection(&This->time_cs);
633 return hr;
634 }
635
636 static const IMediaSeekingVtbl IMediaSeekingPassThru_Vtbl =
637 {
638 MediaSeekingPassThru_QueryInterface,
639 MediaSeekingPassThru_AddRef,
640 MediaSeekingPassThru_Release,
641 MediaSeekingPassThru_GetCapabilities,
642 MediaSeekingPassThru_CheckCapabilities,
643 MediaSeekingPassThru_IsFormatSupported,
644 MediaSeekingPassThru_QueryPreferredFormat,
645 MediaSeekingPassThru_GetTimeFormat,
646 MediaSeekingPassThru_IsUsingTimeFormat,
647 MediaSeekingPassThru_SetTimeFormat,
648 MediaSeekingPassThru_GetDuration,
649 MediaSeekingPassThru_GetStopPosition,
650 MediaSeekingPassThru_GetCurrentPosition,
651 MediaSeekingPassThru_ConvertTimeFormat,
652 MediaSeekingPassThru_SetPositions,
653 MediaSeekingPassThru_GetPositions,
654 MediaSeekingPassThru_GetAvailable,
655 MediaSeekingPassThru_SetRate,
656 MediaSeekingPassThru_GetRate,
657 MediaSeekingPassThru_GetPreroll
658 };
659
MediaPositionPassThru_QueryInterface(IMediaPosition * iface,REFIID riid,LPVOID * ppvObj)660 static HRESULT WINAPI MediaPositionPassThru_QueryInterface(IMediaPosition *iface, REFIID riid, LPVOID *ppvObj)
661 {
662 PassThruImpl *This = impl_from_IMediaPosition(iface);
663
664 TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj);
665
666 return SeekOuter_QueryInterface(This, riid, ppvObj);
667 }
668
MediaPositionPassThru_AddRef(IMediaPosition * iface)669 static ULONG WINAPI MediaPositionPassThru_AddRef(IMediaPosition *iface)
670 {
671 PassThruImpl *This = impl_from_IMediaPosition(iface);
672
673 TRACE("(%p/%p)->()\n", iface, This);
674
675 return SeekOuter_AddRef(This);
676 }
677
MediaPositionPassThru_Release(IMediaPosition * iface)678 static ULONG WINAPI MediaPositionPassThru_Release(IMediaPosition *iface)
679 {
680 PassThruImpl *This = impl_from_IMediaPosition(iface);
681
682 TRACE("(%p/%p)->()\n", iface, This);
683
684 return SeekOuter_Release(This);
685 }
686
MediaPositionPassThru_GetTypeInfoCount(IMediaPosition * iface,UINT * pctinfo)687 static HRESULT WINAPI MediaPositionPassThru_GetTypeInfoCount(IMediaPosition *iface, UINT*pctinfo)
688 {
689 PassThruImpl *This = impl_from_IMediaPosition(iface);
690
691 return BaseDispatchImpl_GetTypeInfoCount(&This->baseDispatch, pctinfo);
692 }
693
MediaPositionPassThru_GetTypeInfo(IMediaPosition * iface,UINT iTInfo,LCID lcid,ITypeInfo ** ppTInfo)694 static HRESULT WINAPI MediaPositionPassThru_GetTypeInfo(IMediaPosition *iface, UINT iTInfo, LCID lcid, ITypeInfo**ppTInfo)
695 {
696 PassThruImpl *This = impl_from_IMediaPosition(iface);
697
698 return BaseDispatchImpl_GetTypeInfo(&This->baseDispatch, &IID_NULL, iTInfo, lcid, ppTInfo);
699 }
700
MediaPositionPassThru_GetIDsOfNames(IMediaPosition * iface,REFIID riid,LPOLESTR * rgszNames,UINT cNames,LCID lcid,DISPID * rgDispId)701 static HRESULT WINAPI MediaPositionPassThru_GetIDsOfNames(IMediaPosition *iface, REFIID riid, LPOLESTR*rgszNames, UINT cNames, LCID lcid, DISPID*rgDispId)
702 {
703 PassThruImpl *This = impl_from_IMediaPosition(iface);
704
705 return BaseDispatchImpl_GetIDsOfNames(&This->baseDispatch, riid, rgszNames, cNames, lcid, rgDispId);
706 }
707
MediaPositionPassThru_Invoke(IMediaPosition * iface,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExepInfo,UINT * puArgErr)708 static HRESULT WINAPI MediaPositionPassThru_Invoke(IMediaPosition *iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS*pDispParams, VARIANT*pVarResult, EXCEPINFO*pExepInfo, UINT*puArgErr)
709 {
710 PassThruImpl *This = impl_from_IMediaPosition(iface);
711 HRESULT hr = S_OK;
712 ITypeInfo *pTypeInfo;
713
714 hr = BaseDispatchImpl_GetTypeInfo(&This->baseDispatch, riid, 1, lcid, &pTypeInfo);
715 if (SUCCEEDED(hr))
716 {
717 hr = ITypeInfo_Invoke(pTypeInfo, &This->IMediaPosition_iface, dispIdMember, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
718 ITypeInfo_Release(pTypeInfo);
719 }
720
721 return hr;
722 }
723
MediaPositionPassThru_get_Duration(IMediaPosition * iface,REFTIME * plength)724 static HRESULT WINAPI MediaPositionPassThru_get_Duration(IMediaPosition *iface, REFTIME *plength)
725 {
726 PassThruImpl *This = impl_from_IMediaPosition(iface);
727 IMediaPosition *pos;
728 HRESULT hr;
729
730 TRACE("(%p)\n", plength);
731
732 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
733 if (SUCCEEDED(hr)) {
734 hr = IMediaPosition_get_Duration(pos, plength);
735 IMediaPosition_Release(pos);
736 }
737 else
738 return E_NOTIMPL;
739 return hr;
740 }
741
MediaPositionPassThru_put_CurrentPosition(IMediaPosition * iface,REFTIME llTime)742 static HRESULT WINAPI MediaPositionPassThru_put_CurrentPosition(IMediaPosition *iface, REFTIME llTime)
743 {
744 PassThruImpl *This = impl_from_IMediaPosition(iface);
745 IMediaPosition *pos;
746 HRESULT hr;
747
748 TRACE("(%s)\n", wine_dbgstr_longlong(llTime));
749
750 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
751 if (SUCCEEDED(hr)) {
752 hr = IMediaPosition_put_CurrentPosition(pos, llTime);
753 IMediaPosition_Release(pos);
754 }
755 else
756 return E_NOTIMPL;
757 return hr;
758 }
759
MediaPositionPassThru_get_CurrentPosition(IMediaPosition * iface,REFTIME * pllTime)760 static HRESULT WINAPI MediaPositionPassThru_get_CurrentPosition(IMediaPosition *iface, REFTIME *pllTime)
761 {
762 PassThruImpl *This = impl_from_IMediaPosition(iface);
763 IMediaPosition *pos;
764 HRESULT hr;
765
766 TRACE("(%p)\n", pllTime);
767
768 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
769 if (SUCCEEDED(hr)) {
770 hr = IMediaPosition_get_CurrentPosition(pos, pllTime);
771 IMediaPosition_Release(pos);
772 }
773 else
774 return E_NOTIMPL;
775 return hr;
776 }
777
MediaPositionPassThru_get_StopTime(IMediaPosition * iface,REFTIME * pllTime)778 static HRESULT WINAPI MediaPositionPassThru_get_StopTime(IMediaPosition *iface, REFTIME *pllTime)
779 {
780 PassThruImpl *This = impl_from_IMediaPosition(iface);
781 IMediaPosition *pos;
782 HRESULT hr;
783
784 TRACE("(%p)\n", pllTime);
785
786 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
787 if (SUCCEEDED(hr)) {
788 hr = IMediaPosition_get_StopTime(pos, pllTime);
789 IMediaPosition_Release(pos);
790 }
791 else
792 return E_NOTIMPL;
793 return hr;
794 }
795
MediaPositionPassThru_put_StopTime(IMediaPosition * iface,REFTIME llTime)796 static HRESULT WINAPI MediaPositionPassThru_put_StopTime(IMediaPosition *iface, REFTIME llTime)
797 {
798 PassThruImpl *This = impl_from_IMediaPosition(iface);
799 IMediaPosition *pos;
800 HRESULT hr;
801
802 TRACE("(%s)\n", wine_dbgstr_longlong(llTime));
803
804 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
805 if (SUCCEEDED(hr)) {
806 hr = IMediaPosition_put_StopTime(pos, llTime);
807 IMediaPosition_Release(pos);
808 }
809 else
810 return E_NOTIMPL;
811 return hr;
812 }
813
MediaPositionPassThru_get_PrerollTime(IMediaPosition * iface,REFTIME * pllTime)814 static HRESULT WINAPI MediaPositionPassThru_get_PrerollTime(IMediaPosition *iface, REFTIME *pllTime)
815 {
816 PassThruImpl *This = impl_from_IMediaPosition(iface);
817 IMediaPosition *pos;
818 HRESULT hr;
819
820 TRACE("(%p)\n", pllTime);
821
822 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
823 if (SUCCEEDED(hr)) {
824 hr = IMediaPosition_get_PrerollTime(pos, pllTime);
825 IMediaPosition_Release(pos);
826 }
827 else
828 return E_NOTIMPL;
829 return hr;
830 }
831
MediaPositionPassThru_put_PrerollTime(IMediaPosition * iface,REFTIME llTime)832 static HRESULT WINAPI MediaPositionPassThru_put_PrerollTime(IMediaPosition *iface, REFTIME llTime)
833 {
834 PassThruImpl *This = impl_from_IMediaPosition(iface);
835 IMediaPosition *pos;
836 HRESULT hr;
837
838 TRACE("(%s)\n", wine_dbgstr_longlong(llTime));
839
840 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
841 if (SUCCEEDED(hr)) {
842 hr = IMediaPosition_put_PrerollTime(pos, llTime);
843 IMediaPosition_Release(pos);
844 }
845 else
846 return E_NOTIMPL;
847 return hr;
848 }
849
MediaPositionPassThru_put_Rate(IMediaPosition * iface,double dRate)850 static HRESULT WINAPI MediaPositionPassThru_put_Rate(IMediaPosition *iface, double dRate)
851 {
852 PassThruImpl *This = impl_from_IMediaPosition(iface);
853 IMediaPosition *pos;
854 HRESULT hr;
855
856 TRACE("(%f)\n", dRate);
857
858 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
859 if (SUCCEEDED(hr)) {
860 hr = IMediaPosition_put_Rate(pos, dRate);
861 IMediaPosition_Release(pos);
862 }
863 else
864 return E_NOTIMPL;
865 return hr;
866 }
867
MediaPositionPassThru_get_Rate(IMediaPosition * iface,double * pdRate)868 static HRESULT WINAPI MediaPositionPassThru_get_Rate(IMediaPosition *iface, double *pdRate)
869 {
870 PassThruImpl *This = impl_from_IMediaPosition(iface);
871 IMediaPosition *pos;
872 HRESULT hr;
873
874 TRACE("(%p)\n", pdRate);
875
876 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
877 if (SUCCEEDED(hr)) {
878 hr = IMediaPosition_get_Rate(pos, pdRate);
879 IMediaPosition_Release(pos);
880 }
881 else
882 return E_NOTIMPL;
883 return hr;
884 }
885
MediaPositionPassThru_CanSeekForward(IMediaPosition * iface,LONG * pCanSeekForward)886 static HRESULT WINAPI MediaPositionPassThru_CanSeekForward(IMediaPosition *iface, LONG *pCanSeekForward)
887 {
888 PassThruImpl *This = impl_from_IMediaPosition(iface);
889 IMediaPosition *pos;
890 HRESULT hr;
891
892 TRACE("(%p)\n", pCanSeekForward);
893
894 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
895 if (SUCCEEDED(hr)) {
896 hr = IMediaPosition_CanSeekForward(pos, pCanSeekForward);
897 IMediaPosition_Release(pos);
898 }
899 else
900 return E_NOTIMPL;
901 return hr;
902 }
903
MediaPositionPassThru_CanSeekBackward(IMediaPosition * iface,LONG * pCanSeekBackward)904 static HRESULT WINAPI MediaPositionPassThru_CanSeekBackward(IMediaPosition *iface, LONG *pCanSeekBackward)
905 {
906 PassThruImpl *This = impl_from_IMediaPosition(iface);
907 IMediaPosition *pos;
908 HRESULT hr;
909
910 TRACE("(%p)\n", pCanSeekBackward);
911
912 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos);
913 if (SUCCEEDED(hr)) {
914 hr = IMediaPosition_CanSeekBackward(pos, pCanSeekBackward);
915 IMediaPosition_Release(pos);
916 }
917 else
918 return E_NOTIMPL;
919 return hr;
920 }
921
922 static const IMediaPositionVtbl IMediaPositionPassThru_Vtbl =
923 {
924 MediaPositionPassThru_QueryInterface,
925 MediaPositionPassThru_AddRef,
926 MediaPositionPassThru_Release,
927 MediaPositionPassThru_GetTypeInfoCount,
928 MediaPositionPassThru_GetTypeInfo,
929 MediaPositionPassThru_GetIDsOfNames,
930 MediaPositionPassThru_Invoke,
931 MediaPositionPassThru_get_Duration,
932 MediaPositionPassThru_put_CurrentPosition,
933 MediaPositionPassThru_get_CurrentPosition,
934 MediaPositionPassThru_get_StopTime,
935 MediaPositionPassThru_put_StopTime,
936 MediaPositionPassThru_get_PrerollTime,
937 MediaPositionPassThru_put_PrerollTime,
938 MediaPositionPassThru_put_Rate,
939 MediaPositionPassThru_get_Rate,
940 MediaPositionPassThru_CanSeekForward,
941 MediaPositionPassThru_CanSeekBackward
942 };
943