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)\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 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(&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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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