taskmgr: Remove a useless commented line.
[wine.git] / dlls / quartz / control.c
blob9ff4c83bf964927cee1d459b9c27f62b2229214f
1 /*
2 * Filter Seeking and Control Interfaces
4 * Copyright 2003 Robert Shearman
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 /* FIXME: critical sections */
22 #include "quartz_private.h"
23 #include "control_private.h"
25 #include "uuids.h"
26 #include "wine/debug.h"
28 #include <assert.h>
30 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
32 static const IMediaSeekingVtbl IMediaSeekingPassThru_Vtbl;
34 typedef struct PassThruImpl {
35 const ISeekingPassThruVtbl *IPassThru_vtbl;
36 const IUnknownVtbl *IInner_vtbl;
37 const IMediaSeekingVtbl *IMediaSeeking_vtbl;
39 LONG ref;
40 IUnknown * pUnkOuter;
41 IPin * pin;
42 BOOL bUnkOuterValid;
43 BOOL bAggregatable;
44 BOOL renderer;
45 CRITICAL_SECTION time_cs;
46 BOOL timevalid;
47 REFERENCE_TIME time_earliest;
48 } PassThruImpl;
50 static HRESULT WINAPI SeekInner_QueryInterface(IUnknown * iface,
51 REFIID riid,
52 LPVOID *ppvObj) {
53 ICOM_THIS_MULTI(PassThruImpl, IInner_vtbl, iface);
54 TRACE("(%p)->(%s (%p), %p)\n", This, debugstr_guid(riid), riid, ppvObj);
56 if (This->bAggregatable)
57 This->bUnkOuterValid = TRUE;
59 if (IsEqualGUID(&IID_IUnknown, riid))
61 *ppvObj = &(This->IInner_vtbl);
62 TRACE(" returning IUnknown interface (%p)\n", *ppvObj);
63 } else if (IsEqualGUID(&IID_ISeekingPassThru, riid)) {
64 *ppvObj = &(This->IPassThru_vtbl);
65 TRACE(" returning ISeekingPassThru interface (%p)\n", *ppvObj);
66 } else if (IsEqualGUID(&IID_IMediaSeeking, riid)) {
67 *ppvObj = &(This->IMediaSeeking_vtbl);
68 TRACE(" returning IMediaSeeking interface (%p)\n", *ppvObj);
69 } else {
70 *ppvObj = NULL;
71 FIXME("unknown interface %s\n", debugstr_guid(riid));
72 return E_NOINTERFACE;
75 IUnknown_AddRef((IUnknown *)(*ppvObj));
76 return S_OK;
79 static ULONG WINAPI SeekInner_AddRef(IUnknown * iface) {
80 ICOM_THIS_MULTI(PassThruImpl, IInner_vtbl, iface);
81 ULONG ref = InterlockedIncrement(&This->ref);
83 TRACE("(%p)->(): new ref = %d\n", This, ref);
85 return ref;
88 static ULONG WINAPI SeekInner_Release(IUnknown * iface) {
89 ICOM_THIS_MULTI(PassThruImpl, IInner_vtbl, iface);
90 ULONG ref = InterlockedDecrement(&This->ref);
92 TRACE("(%p)->(): new ref = %d\n", This, ref);
94 if (ref == 0)
96 This->time_cs.DebugInfo->Spare[0] = 0;
97 DeleteCriticalSection(&This->time_cs);
98 CoTaskMemFree(This);
100 return ref;
103 static const IUnknownVtbl IInner_VTable =
105 SeekInner_QueryInterface,
106 SeekInner_AddRef,
107 SeekInner_Release
110 /* Generic functions for aggregation */
111 static HRESULT SeekOuter_QueryInterface(PassThruImpl *This, REFIID riid, LPVOID *ppv)
113 if (This->bAggregatable)
114 This->bUnkOuterValid = TRUE;
116 if (This->pUnkOuter)
118 if (This->bAggregatable)
119 return IUnknown_QueryInterface(This->pUnkOuter, riid, ppv);
121 if (IsEqualIID(riid, &IID_IUnknown))
123 HRESULT hr;
125 IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
126 hr = IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
127 IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
128 This->bAggregatable = TRUE;
129 return hr;
132 *ppv = NULL;
133 return E_NOINTERFACE;
136 return IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
139 static ULONG SeekOuter_AddRef(PassThruImpl *This)
141 if (This->pUnkOuter && This->bUnkOuterValid)
142 return IUnknown_AddRef(This->pUnkOuter);
143 return IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
146 static ULONG SeekOuter_Release(PassThruImpl *This)
148 if (This->pUnkOuter && This->bUnkOuterValid)
149 return IUnknown_Release(This->pUnkOuter);
150 return IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
153 static HRESULT WINAPI SeekingPassThru_QueryInterface(ISeekingPassThru *iface, REFIID riid, LPVOID *ppvObj)
155 ICOM_THIS_MULTI(PassThruImpl, IPassThru_vtbl, iface);
157 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
159 return SeekOuter_QueryInterface(This, riid, ppvObj);
162 static ULONG WINAPI SeekingPassThru_AddRef(ISeekingPassThru *iface)
164 ICOM_THIS_MULTI(PassThruImpl, IPassThru_vtbl, iface);
166 TRACE("(%p/%p)->()\n", This, iface);
168 return SeekOuter_AddRef(This);
171 static ULONG WINAPI SeekingPassThru_Release(ISeekingPassThru *iface)
173 ICOM_THIS_MULTI(PassThruImpl, IPassThru_vtbl, iface);
175 TRACE("(%p/%p)->()\n", This, iface);
177 return SeekOuter_Release(This);
180 static HRESULT WINAPI SeekingPassThru_Init(ISeekingPassThru *iface, BOOL renderer, IPin *pin)
182 ICOM_THIS_MULTI(PassThruImpl, IPassThru_vtbl, iface);
184 TRACE("(%p/%p)->(%d, %p)\n", This, iface, renderer, pin);
186 if (This->pin)
187 FIXME("Re-initializing?\n");
189 This->renderer = renderer;
190 This->pin = pin;
192 return S_OK;
195 static const ISeekingPassThruVtbl ISeekingPassThru_Vtbl =
197 SeekingPassThru_QueryInterface,
198 SeekingPassThru_AddRef,
199 SeekingPassThru_Release,
200 SeekingPassThru_Init
203 HRESULT SeekingPassThru_create(IUnknown *pUnkOuter, LPVOID *ppObj)
205 PassThruImpl *fimpl;
207 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
209 *ppObj = fimpl = CoTaskMemAlloc(sizeof(*fimpl));
210 if (!fimpl)
211 return E_OUTOFMEMORY;
213 fimpl->pUnkOuter = pUnkOuter;
214 fimpl->bUnkOuterValid = FALSE;
215 fimpl->bAggregatable = FALSE;
216 fimpl->IInner_vtbl = &IInner_VTable;
217 fimpl->IPassThru_vtbl = &ISeekingPassThru_Vtbl;
218 fimpl->IMediaSeeking_vtbl = &IMediaSeekingPassThru_Vtbl;
219 fimpl->ref = 1;
220 fimpl->pin = NULL;
221 fimpl->timevalid = 0;
222 InitializeCriticalSection(&fimpl->time_cs);
223 fimpl->time_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": PassThruImpl.time_cs");
224 return S_OK;
227 static HRESULT WINAPI MediaSeekingPassThru_QueryInterface(IMediaSeeking *iface, REFIID riid, LPVOID *ppvObj)
229 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
231 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
233 return SeekOuter_QueryInterface(This, riid, ppvObj);
236 static ULONG WINAPI MediaSeekingPassThru_AddRef(IMediaSeeking *iface)
238 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
240 TRACE("(%p/%p)->()\n", iface, This);
242 return SeekOuter_AddRef(This);
245 static ULONG WINAPI MediaSeekingPassThru_Release(IMediaSeeking *iface)
247 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
249 TRACE("(%p/%p)->()\n", iface, This);
251 return SeekOuter_Release(This);
254 static HRESULT get_connected(PassThruImpl *This, IMediaSeeking **seek) {
255 HRESULT hr;
256 IPin *pin;
257 *seek = NULL;
258 hr = IPin_ConnectedTo(This->pin, &pin);
259 if (FAILED(hr))
260 return VFW_E_NOT_CONNECTED;
261 hr = IPin_QueryInterface(pin, &IID_IMediaSeeking, (void**)seek);
262 IPin_Release(pin);
263 if (FAILED(hr))
264 hr = E_NOTIMPL;
265 return hr;
268 static HRESULT WINAPI MediaSeekingPassThru_GetCapabilities(IMediaSeeking * iface, DWORD * pCapabilities)
270 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
271 IMediaSeeking *seek;
272 HRESULT hr;
273 TRACE("(%p/%p)->(%p)\n", iface, This, pCapabilities);
274 hr = get_connected(This, &seek);
275 if (SUCCEEDED(hr)) {
276 hr = IMediaSeeking_GetCapabilities(seek, pCapabilities);
277 IMediaSeeking_Release(seek);
279 else
280 return E_NOTIMPL;
281 return hr;
284 static HRESULT WINAPI MediaSeekingPassThru_CheckCapabilities(IMediaSeeking * iface, DWORD * pCapabilities)
286 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
287 IMediaSeeking *seek;
288 HRESULT hr;
289 TRACE("(%p/%p)->(%p)\n", iface, This, pCapabilities);
290 hr = get_connected(This, &seek);
291 if (SUCCEEDED(hr)) {
292 hr = IMediaSeeking_CheckCapabilities(seek, pCapabilities);
293 IMediaSeeking_Release(seek);
295 else
296 return E_NOTIMPL;
297 return hr;
300 static HRESULT WINAPI MediaSeekingPassThru_IsFormatSupported(IMediaSeeking * iface, const GUID * pFormat)
302 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
303 IMediaSeeking *seek;
304 HRESULT hr;
305 TRACE("(%p/%p)->(%s)\n", iface, This, qzdebugstr_guid(pFormat));
306 hr = get_connected(This, &seek);
307 if (SUCCEEDED(hr)) {
308 hr = IMediaSeeking_IsFormatSupported(seek, pFormat);
309 IMediaSeeking_Release(seek);
311 else
312 return E_NOTIMPL;
313 return hr;
316 static HRESULT WINAPI MediaSeekingPassThru_QueryPreferredFormat(IMediaSeeking * iface, GUID * pFormat)
318 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
319 IMediaSeeking *seek;
320 HRESULT hr;
321 TRACE("(%p/%p)->(%p)\n", iface, This, pFormat);
322 hr = get_connected(This, &seek);
323 if (SUCCEEDED(hr)) {
324 hr = IMediaSeeking_QueryPreferredFormat(seek, pFormat);
325 IMediaSeeking_Release(seek);
327 else
328 return E_NOTIMPL;
329 return hr;
332 static HRESULT WINAPI MediaSeekingPassThru_GetTimeFormat(IMediaSeeking * iface, GUID * pFormat)
334 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
335 IMediaSeeking *seek;
336 HRESULT hr;
337 TRACE("(%p/%p)->(%p)\n", iface, This, pFormat);
338 hr = get_connected(This, &seek);
339 if (SUCCEEDED(hr)) {
340 hr = IMediaSeeking_GetTimeFormat(seek, pFormat);
341 IMediaSeeking_Release(seek);
343 else
344 return E_NOTIMPL;
345 return hr;
348 static HRESULT WINAPI MediaSeekingPassThru_IsUsingTimeFormat(IMediaSeeking * iface, const GUID * pFormat)
350 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
351 IMediaSeeking *seek;
352 HRESULT hr;
353 TRACE("(%p/%p)->(%s)\n", iface, This, qzdebugstr_guid(pFormat));
354 hr = get_connected(This, &seek);
355 if (SUCCEEDED(hr)) {
356 hr = IMediaSeeking_IsUsingTimeFormat(seek, pFormat);
357 IMediaSeeking_Release(seek);
359 else
360 return E_NOTIMPL;
361 return hr;
364 static HRESULT WINAPI MediaSeekingPassThru_SetTimeFormat(IMediaSeeking * iface, const GUID * pFormat)
366 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
367 IMediaSeeking *seek;
368 HRESULT hr;
369 TRACE("(%p/%p)->(%s)\n", iface, This, qzdebugstr_guid(pFormat));
370 hr = get_connected(This, &seek);
371 if (SUCCEEDED(hr)) {
372 hr = IMediaSeeking_SetTimeFormat(seek, pFormat);
373 IMediaSeeking_Release(seek);
375 else
376 return E_NOTIMPL;
377 return hr;
380 static HRESULT WINAPI MediaSeekingPassThru_GetDuration(IMediaSeeking * iface, LONGLONG * pDuration)
382 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
383 IMediaSeeking *seek;
384 HRESULT hr;
385 TRACE("(%p/%p)->(%p)\n", iface, This, pDuration);
386 hr = get_connected(This, &seek);
387 if (SUCCEEDED(hr)) {
388 hr = IMediaSeeking_GetDuration(seek, pDuration);
389 IMediaSeeking_Release(seek);
391 else
392 return E_NOTIMPL;
393 return hr;
396 static HRESULT WINAPI MediaSeekingPassThru_GetStopPosition(IMediaSeeking * iface, LONGLONG * pStop)
398 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
399 IMediaSeeking *seek;
400 HRESULT hr;
401 TRACE("(%p/%p)->(%p)\n", iface, This, pStop);
402 hr = get_connected(This, &seek);
403 if (SUCCEEDED(hr)) {
404 hr = IMediaSeeking_GetStopPosition(seek, pStop);
405 IMediaSeeking_Release(seek);
407 else
408 return E_NOTIMPL;
409 return hr;
412 static HRESULT WINAPI MediaSeekingPassThru_GetCurrentPosition(IMediaSeeking * iface, LONGLONG * pCurrent)
414 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
415 IMediaSeeking *seek;
416 HRESULT hr = S_OK;
417 TRACE("(%p/%p)->(%p)\n", iface, This, pCurrent);
418 if (!pCurrent)
419 return E_POINTER;
420 EnterCriticalSection(&This->time_cs);
421 if (This->timevalid)
422 *pCurrent = This->time_earliest;
423 else
424 hr = E_FAIL;
425 LeaveCriticalSection(&This->time_cs);
426 if (SUCCEEDED(hr)) {
427 hr = IMediaSeeking_ConvertTimeFormat(iface, pCurrent, NULL, *pCurrent, &TIME_FORMAT_MEDIA_TIME);
428 return hr;
430 hr = get_connected(This, &seek);
431 if (SUCCEEDED(hr)) {
432 hr = IMediaSeeking_GetCurrentPosition(seek, pCurrent);
433 IMediaSeeking_Release(seek);
435 else
436 return E_NOTIMPL;
437 return hr;
440 static HRESULT WINAPI MediaSeekingPassThru_ConvertTimeFormat(IMediaSeeking * iface, LONGLONG * pTarget, const GUID * pTargetFormat, LONGLONG Source, const GUID * pSourceFormat)
442 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
443 IMediaSeeking *seek;
444 HRESULT hr;
445 TRACE("(%p/%p)->(%p,%s,%x%08x,%s)\n", iface, This, pTarget, debugstr_guid(pTargetFormat), (DWORD)(Source>>32), (DWORD)Source, debugstr_guid(pSourceFormat));
446 hr = get_connected(This, &seek);
447 if (SUCCEEDED(hr)) {
448 hr = IMediaSeeking_ConvertTimeFormat(seek, pTarget, pTargetFormat, Source, pSourceFormat);
449 IMediaSeeking_Release(seek);
451 else
452 return E_NOTIMPL;
453 return hr;
456 static HRESULT WINAPI MediaSeekingPassThru_SetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, DWORD dwCurrentFlags, LONGLONG * pStop, DWORD dwStopFlags)
458 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
459 IMediaSeeking *seek;
460 HRESULT hr;
461 TRACE("(%p/%p)->(%p,%x,%p,%x)\n", iface, This, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
462 hr = get_connected(This, &seek);
463 if (SUCCEEDED(hr)) {
464 hr = IMediaSeeking_SetPositions(seek, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
465 IMediaSeeking_Release(seek);
466 } else if (hr == VFW_E_NOT_CONNECTED)
467 hr = S_OK;
468 return hr;
471 static HRESULT WINAPI MediaSeekingPassThru_GetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, LONGLONG * pStop)
473 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
474 IMediaSeeking *seek;
475 HRESULT hr;
476 TRACE("(%p/%p)->(%p, %p)\n", iface, This, pCurrent, pStop);
477 hr = get_connected(This, &seek);
478 if (SUCCEEDED(hr)) {
479 hr = IMediaSeeking_GetPositions(seek, pCurrent, pStop);
480 IMediaSeeking_Release(seek);
482 else
483 return E_NOTIMPL;
484 return hr;
487 static HRESULT WINAPI MediaSeekingPassThru_GetAvailable(IMediaSeeking * iface, LONGLONG * pEarliest, LONGLONG * pLatest)
489 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
490 IMediaSeeking *seek;
491 HRESULT hr;
492 TRACE("(%p/%p)->(%p,%p)\n", iface, This, pEarliest, pLatest);
493 hr = get_connected(This, &seek);
494 if (SUCCEEDED(hr)) {
495 hr = IMediaSeeking_GetAvailable(seek, pEarliest, pLatest);
496 IMediaSeeking_Release(seek);
498 else
499 return E_NOTIMPL;
500 return hr;
503 static HRESULT WINAPI MediaSeekingPassThru_SetRate(IMediaSeeking * iface, double dRate)
505 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
506 IMediaSeeking *seek;
507 HRESULT hr;
508 TRACE("(%p/%p)->(%e)\n", iface, This, dRate);
509 hr = get_connected(This, &seek);
510 if (SUCCEEDED(hr)) {
511 hr = IMediaSeeking_SetRate(seek, dRate);
512 IMediaSeeking_Release(seek);
514 else
515 return E_NOTIMPL;
516 return hr;
519 static HRESULT WINAPI MediaSeekingPassThru_GetRate(IMediaSeeking * iface, double * dRate)
521 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
522 IMediaSeeking *seek;
523 HRESULT hr;
524 TRACE("(%p/%p)->(%p)\n", iface, This, dRate);
525 hr = get_connected(This, &seek);
526 if (SUCCEEDED(hr)) {
527 hr = IMediaSeeking_GetRate(seek, dRate);
528 IMediaSeeking_Release(seek);
530 else
531 return E_NOTIMPL;
532 return hr;
535 static HRESULT WINAPI MediaSeekingPassThru_GetPreroll(IMediaSeeking * iface, LONGLONG * pPreroll)
537 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
538 IMediaSeeking *seek;
539 HRESULT hr;
540 TRACE("(%p)\n", pPreroll);
541 hr = get_connected(This, &seek);
542 if (SUCCEEDED(hr)) {
543 hr = IMediaSeeking_GetPreroll(seek, pPreroll);
544 IMediaSeeking_Release(seek);
546 else
547 return E_NOTIMPL;
548 return hr;
551 void MediaSeekingPassThru_RegisterMediaTime(IUnknown *iface, REFERENCE_TIME start) {
552 ICOM_THIS_MULTI(PassThruImpl, IInner_vtbl, iface);
553 EnterCriticalSection(&This->time_cs);
554 This->time_earliest = start;
555 This->timevalid = 1;
556 LeaveCriticalSection(&This->time_cs);
559 void MediaSeekingPassThru_ResetMediaTime(IUnknown *iface) {
560 ICOM_THIS_MULTI(PassThruImpl, IInner_vtbl, iface);
561 EnterCriticalSection(&This->time_cs);
562 This->timevalid = 0;
563 LeaveCriticalSection(&This->time_cs);
566 void MediaSeekingPassThru_EOS(IUnknown *iface) {
567 ICOM_THIS_MULTI(PassThruImpl, IInner_vtbl, iface);
568 REFERENCE_TIME time;
569 HRESULT hr;
570 hr = IMediaSeeking_GetStopPosition((IMediaSeeking*)&This->IMediaSeeking_vtbl, &time);
571 EnterCriticalSection(&This->time_cs);
572 if (SUCCEEDED(hr)) {
573 This->timevalid = 1;
574 This->time_earliest = time;
575 } else
576 This->timevalid = 0;
577 LeaveCriticalSection(&This->time_cs);
580 static const IMediaSeekingVtbl IMediaSeekingPassThru_Vtbl =
582 MediaSeekingPassThru_QueryInterface,
583 MediaSeekingPassThru_AddRef,
584 MediaSeekingPassThru_Release,
585 MediaSeekingPassThru_GetCapabilities,
586 MediaSeekingPassThru_CheckCapabilities,
587 MediaSeekingPassThru_IsFormatSupported,
588 MediaSeekingPassThru_QueryPreferredFormat,
589 MediaSeekingPassThru_GetTimeFormat,
590 MediaSeekingPassThru_IsUsingTimeFormat,
591 MediaSeekingPassThru_SetTimeFormat,
592 MediaSeekingPassThru_GetDuration,
593 MediaSeekingPassThru_GetStopPosition,
594 MediaSeekingPassThru_GetCurrentPosition,
595 MediaSeekingPassThru_ConvertTimeFormat,
596 MediaSeekingPassThru_SetPositions,
597 MediaSeekingPassThru_GetPositions,
598 MediaSeekingPassThru_GetAvailable,
599 MediaSeekingPassThru_SetRate,
600 MediaSeekingPassThru_GetRate,
601 MediaSeekingPassThru_GetPreroll