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 if (FAILED(hr)) 230 return hr; 231 232 IUnknown_QueryInterface(*ppPassThru, &IID_ISeekingPassThru, (void**)&passthru); 233 hr = ISeekingPassThru_Init(passthru, bRenderer, pPin); 234 ISeekingPassThru_Release(passthru); 235 236 return hr; 237 } 238 239 HRESULT WINAPI PosPassThru_Construct(IUnknown *pUnkOuter, LPVOID *ppPassThru) 240 { 241 PassThruImpl *fimpl; 242 243 TRACE("(%p,%p)\n", pUnkOuter, ppPassThru); 244 245 *ppPassThru = fimpl = CoTaskMemAlloc(sizeof(*fimpl)); 246 if (!fimpl) 247 return E_OUTOFMEMORY; 248 249 fimpl->outer_unk = pUnkOuter; 250 fimpl->bUnkOuterValid = FALSE; 251 fimpl->bAggregatable = FALSE; 252 fimpl->IUnknown_inner.lpVtbl = &IInner_VTable; 253 fimpl->ISeekingPassThru_iface.lpVtbl = &ISeekingPassThru_Vtbl; 254 fimpl->IMediaSeeking_iface.lpVtbl = &IMediaSeekingPassThru_Vtbl; 255 fimpl->IMediaPosition_iface.lpVtbl = &IMediaPositionPassThru_Vtbl; 256 fimpl->ref = 1; 257 fimpl->pin = NULL; 258 fimpl->timevalid = FALSE; 259 InitializeCriticalSection(&fimpl->time_cs); 260 fimpl->time_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": PassThruImpl.time_cs"); 261 BaseDispatch_Init(&fimpl->baseDispatch, &IID_IMediaPosition); 262 return S_OK; 263 } 264 265 static HRESULT WINAPI MediaSeekingPassThru_QueryInterface(IMediaSeeking *iface, REFIID riid, LPVOID *ppvObj) 266 { 267 PassThruImpl *This = impl_from_IMediaSeeking(iface); 268 269 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj); 270 271 return SeekOuter_QueryInterface(This, riid, ppvObj); 272 } 273 274 static ULONG WINAPI MediaSeekingPassThru_AddRef(IMediaSeeking *iface) 275 { 276 PassThruImpl *This = impl_from_IMediaSeeking(iface); 277 278 TRACE("(%p/%p)->()\n", iface, This); 279 280 return SeekOuter_AddRef(This); 281 } 282 283 static ULONG WINAPI MediaSeekingPassThru_Release(IMediaSeeking *iface) 284 { 285 PassThruImpl *This = impl_from_IMediaSeeking(iface); 286 287 TRACE("(%p/%p)->()\n", iface, This); 288 289 return SeekOuter_Release(This); 290 } 291 292 static HRESULT get_connected(PassThruImpl *This, REFIID riid, LPVOID *ppvObj) { 293 HRESULT hr; 294 IPin *pin; 295 *ppvObj = NULL; 296 hr = IPin_ConnectedTo(This->pin, &pin); 297 if (FAILED(hr)) 298 return VFW_E_NOT_CONNECTED; 299 hr = IPin_QueryInterface(pin, riid, ppvObj); 300 IPin_Release(pin); 301 if (FAILED(hr)) 302 hr = E_NOTIMPL; 303 return hr; 304 } 305 306 static HRESULT WINAPI MediaSeekingPassThru_GetCapabilities(IMediaSeeking * iface, DWORD * pCapabilities) 307 { 308 PassThruImpl *This = impl_from_IMediaSeeking(iface); 309 IMediaSeeking *seek; 310 HRESULT hr; 311 TRACE("(%p/%p)->(%p)\n", iface, This, pCapabilities); 312 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek); 313 if (SUCCEEDED(hr)) { 314 hr = IMediaSeeking_GetCapabilities(seek, pCapabilities); 315 IMediaSeeking_Release(seek); 316 } 317 else 318 return E_NOTIMPL; 319 return hr; 320 } 321 322 static HRESULT WINAPI MediaSeekingPassThru_CheckCapabilities(IMediaSeeking * iface, DWORD * pCapabilities) 323 { 324 PassThruImpl *This = impl_from_IMediaSeeking(iface); 325 IMediaSeeking *seek; 326 HRESULT hr; 327 TRACE("(%p/%p)->(%p)\n", iface, This, pCapabilities); 328 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek); 329 if (SUCCEEDED(hr)) { 330 hr = IMediaSeeking_CheckCapabilities(seek, pCapabilities); 331 IMediaSeeking_Release(seek); 332 } 333 else 334 return E_NOTIMPL; 335 return hr; 336 } 337 338 static HRESULT WINAPI MediaSeekingPassThru_IsFormatSupported(IMediaSeeking * iface, const GUID * pFormat) 339 { 340 PassThruImpl *This = impl_from_IMediaSeeking(iface); 341 IMediaSeeking *seek; 342 HRESULT hr; 343 TRACE("(%p/%p)->(%s)\n", iface, This, debugstr_guid(pFormat)); 344 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek); 345 if (SUCCEEDED(hr)) { 346 hr = IMediaSeeking_IsFormatSupported(seek, pFormat); 347 IMediaSeeking_Release(seek); 348 } 349 else 350 return E_NOTIMPL; 351 return hr; 352 } 353 354 static HRESULT WINAPI MediaSeekingPassThru_QueryPreferredFormat(IMediaSeeking * iface, GUID * pFormat) 355 { 356 PassThruImpl *This = impl_from_IMediaSeeking(iface); 357 IMediaSeeking *seek; 358 HRESULT hr; 359 TRACE("(%p/%p)->(%p)\n", iface, This, pFormat); 360 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek); 361 if (SUCCEEDED(hr)) { 362 hr = IMediaSeeking_QueryPreferredFormat(seek, pFormat); 363 IMediaSeeking_Release(seek); 364 } 365 else 366 return E_NOTIMPL; 367 return hr; 368 } 369 370 static HRESULT WINAPI MediaSeekingPassThru_GetTimeFormat(IMediaSeeking * iface, GUID * pFormat) 371 { 372 PassThruImpl *This = impl_from_IMediaSeeking(iface); 373 IMediaSeeking *seek; 374 HRESULT hr; 375 TRACE("(%p/%p)->(%p)\n", iface, This, pFormat); 376 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek); 377 if (SUCCEEDED(hr)) { 378 hr = IMediaSeeking_GetTimeFormat(seek, pFormat); 379 IMediaSeeking_Release(seek); 380 } 381 else 382 return E_NOTIMPL; 383 return hr; 384 } 385 386 static HRESULT WINAPI MediaSeekingPassThru_IsUsingTimeFormat(IMediaSeeking * iface, const GUID * pFormat) 387 { 388 PassThruImpl *This = impl_from_IMediaSeeking(iface); 389 IMediaSeeking *seek; 390 HRESULT hr; 391 TRACE("(%p/%p)->(%s)\n", iface, This, debugstr_guid(pFormat)); 392 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek); 393 if (SUCCEEDED(hr)) { 394 hr = IMediaSeeking_IsUsingTimeFormat(seek, pFormat); 395 IMediaSeeking_Release(seek); 396 } 397 else 398 return E_NOTIMPL; 399 return hr; 400 } 401 402 static HRESULT WINAPI MediaSeekingPassThru_SetTimeFormat(IMediaSeeking * iface, const GUID * pFormat) 403 { 404 PassThruImpl *This = impl_from_IMediaSeeking(iface); 405 IMediaSeeking *seek; 406 HRESULT hr; 407 TRACE("(%p/%p)->(%s)\n", iface, This, debugstr_guid(pFormat)); 408 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek); 409 if (SUCCEEDED(hr)) { 410 hr = IMediaSeeking_SetTimeFormat(seek, pFormat); 411 IMediaSeeking_Release(seek); 412 } 413 else 414 return E_NOTIMPL; 415 return hr; 416 } 417 418 static HRESULT WINAPI MediaSeekingPassThru_GetDuration(IMediaSeeking * iface, LONGLONG * pDuration) 419 { 420 PassThruImpl *This = impl_from_IMediaSeeking(iface); 421 IMediaSeeking *seek; 422 HRESULT hr; 423 TRACE("(%p/%p)->(%p)\n", iface, This, pDuration); 424 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek); 425 if (SUCCEEDED(hr)) { 426 hr = IMediaSeeking_GetDuration(seek, pDuration); 427 IMediaSeeking_Release(seek); 428 } 429 else 430 return E_NOTIMPL; 431 return hr; 432 } 433 434 static HRESULT WINAPI MediaSeekingPassThru_GetStopPosition(IMediaSeeking * iface, LONGLONG * pStop) 435 { 436 PassThruImpl *This = impl_from_IMediaSeeking(iface); 437 IMediaSeeking *seek; 438 HRESULT hr; 439 TRACE("(%p/%p)->(%p)\n", iface, This, pStop); 440 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek); 441 if (SUCCEEDED(hr)) { 442 hr = IMediaSeeking_GetStopPosition(seek, pStop); 443 IMediaSeeking_Release(seek); 444 } 445 else 446 return E_NOTIMPL; 447 return hr; 448 } 449 450 static HRESULT WINAPI MediaSeekingPassThru_GetCurrentPosition(IMediaSeeking * iface, LONGLONG * pCurrent) 451 { 452 PassThruImpl *This = impl_from_IMediaSeeking(iface); 453 IMediaSeeking *seek; 454 HRESULT hr = S_OK; 455 TRACE("(%p/%p)->(%p)\n", iface, This, pCurrent); 456 if (!pCurrent) 457 return E_POINTER; 458 EnterCriticalSection(&This->time_cs); 459 if (This->timevalid) 460 *pCurrent = This->time_earliest; 461 else 462 hr = E_FAIL; 463 LeaveCriticalSection(&This->time_cs); 464 if (SUCCEEDED(hr)) { 465 hr = IMediaSeeking_ConvertTimeFormat(iface, pCurrent, NULL, *pCurrent, &TIME_FORMAT_MEDIA_TIME); 466 return hr; 467 } 468 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek); 469 if (SUCCEEDED(hr)) { 470 hr = IMediaSeeking_GetCurrentPosition(seek, pCurrent); 471 IMediaSeeking_Release(seek); 472 } 473 else 474 return E_NOTIMPL; 475 return hr; 476 } 477 478 static HRESULT WINAPI MediaSeekingPassThru_ConvertTimeFormat(IMediaSeeking * iface, LONGLONG * pTarget, const GUID * pTargetFormat, LONGLONG Source, const GUID * pSourceFormat) 479 { 480 PassThruImpl *This = impl_from_IMediaSeeking(iface); 481 IMediaSeeking *seek; 482 HRESULT hr; 483 TRACE("(%p/%p)->(%p,%s,%x%08x,%s)\n", iface, This, pTarget, debugstr_guid(pTargetFormat), (DWORD)(Source>>32), (DWORD)Source, debugstr_guid(pSourceFormat)); 484 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek); 485 if (SUCCEEDED(hr)) { 486 hr = IMediaSeeking_ConvertTimeFormat(seek, pTarget, pTargetFormat, Source, pSourceFormat); 487 IMediaSeeking_Release(seek); 488 } 489 else 490 return E_NOTIMPL; 491 return hr; 492 } 493 494 static HRESULT WINAPI MediaSeekingPassThru_SetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, DWORD dwCurrentFlags, LONGLONG * pStop, DWORD dwStopFlags) 495 { 496 PassThruImpl *This = impl_from_IMediaSeeking(iface); 497 IMediaSeeking *seek; 498 HRESULT hr; 499 TRACE("(%p/%p)->(%p,%x,%p,%x)\n", iface, This, pCurrent, dwCurrentFlags, pStop, dwStopFlags); 500 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek); 501 if (SUCCEEDED(hr)) { 502 hr = IMediaSeeking_SetPositions(seek, pCurrent, dwCurrentFlags, pStop, dwStopFlags); 503 IMediaSeeking_Release(seek); 504 } else if (hr == VFW_E_NOT_CONNECTED) 505 hr = S_OK; 506 return hr; 507 } 508 509 static HRESULT WINAPI MediaSeekingPassThru_GetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, LONGLONG * pStop) 510 { 511 PassThruImpl *This = impl_from_IMediaSeeking(iface); 512 IMediaSeeking *seek; 513 HRESULT hr; 514 TRACE("(%p/%p)->(%p, %p)\n", iface, This, pCurrent, pStop); 515 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek); 516 if (SUCCEEDED(hr)) { 517 hr = IMediaSeeking_GetPositions(seek, pCurrent, pStop); 518 IMediaSeeking_Release(seek); 519 } else if (hr == VFW_E_NOT_CONNECTED) { 520 *pCurrent = 0; 521 *pStop = 0; 522 hr = S_OK; 523 } 524 return hr; 525 } 526 527 static HRESULT WINAPI MediaSeekingPassThru_GetAvailable(IMediaSeeking * iface, LONGLONG * pEarliest, LONGLONG * pLatest) 528 { 529 PassThruImpl *This = impl_from_IMediaSeeking(iface); 530 IMediaSeeking *seek; 531 HRESULT hr; 532 TRACE("(%p/%p)->(%p,%p)\n", iface, This, pEarliest, pLatest); 533 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek); 534 if (SUCCEEDED(hr)) { 535 hr = IMediaSeeking_GetAvailable(seek, pEarliest, pLatest); 536 IMediaSeeking_Release(seek); 537 } 538 else 539 return E_NOTIMPL; 540 return hr; 541 } 542 543 static HRESULT WINAPI MediaSeekingPassThru_SetRate(IMediaSeeking * iface, double dRate) 544 { 545 PassThruImpl *This = impl_from_IMediaSeeking(iface); 546 IMediaSeeking *seek; 547 HRESULT hr; 548 TRACE("(%p/%p)->(%e)\n", iface, This, dRate); 549 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek); 550 if (SUCCEEDED(hr)) { 551 hr = IMediaSeeking_SetRate(seek, dRate); 552 IMediaSeeking_Release(seek); 553 } 554 else 555 return E_NOTIMPL; 556 return hr; 557 } 558 559 static HRESULT WINAPI MediaSeekingPassThru_GetRate(IMediaSeeking * iface, double * dRate) 560 { 561 PassThruImpl *This = impl_from_IMediaSeeking(iface); 562 IMediaSeeking *seek; 563 HRESULT hr; 564 TRACE("(%p/%p)->(%p)\n", iface, This, dRate); 565 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek); 566 if (SUCCEEDED(hr)) { 567 hr = IMediaSeeking_GetRate(seek, dRate); 568 IMediaSeeking_Release(seek); 569 } 570 else 571 return E_NOTIMPL; 572 return hr; 573 } 574 575 static HRESULT WINAPI MediaSeekingPassThru_GetPreroll(IMediaSeeking * iface, LONGLONG * pPreroll) 576 { 577 PassThruImpl *This = impl_from_IMediaSeeking(iface); 578 IMediaSeeking *seek; 579 HRESULT hr; 580 TRACE("(%p)\n", pPreroll); 581 hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek); 582 if (SUCCEEDED(hr)) { 583 hr = IMediaSeeking_GetPreroll(seek, pPreroll); 584 IMediaSeeking_Release(seek); 585 } 586 else 587 return E_NOTIMPL; 588 return hr; 589 } 590 591 HRESULT WINAPI RendererPosPassThru_RegisterMediaTime(IUnknown *iface, REFERENCE_TIME start) 592 { 593 PassThruImpl *This = impl_from_IUnknown_inner(iface); 594 EnterCriticalSection(&This->time_cs); 595 This->time_earliest = start; 596 This->timevalid = TRUE; 597 LeaveCriticalSection(&This->time_cs); 598 return S_OK; 599 } 600 601 HRESULT WINAPI RendererPosPassThru_ResetMediaTime(IUnknown *iface) 602 { 603 PassThruImpl *This = impl_from_IUnknown_inner(iface); 604 EnterCriticalSection(&This->time_cs); 605 This->timevalid = FALSE; 606 LeaveCriticalSection(&This->time_cs); 607 return S_OK; 608 } 609 610 HRESULT WINAPI RendererPosPassThru_EOS(IUnknown *iface) 611 { 612 PassThruImpl *This = impl_from_IUnknown_inner(iface); 613 REFERENCE_TIME time; 614 HRESULT hr; 615 hr = IMediaSeeking_GetStopPosition(&This->IMediaSeeking_iface, &time); 616 EnterCriticalSection(&This->time_cs); 617 if (SUCCEEDED(hr)) { 618 This->timevalid = TRUE; 619 This->time_earliest = time; 620 } else 621 This->timevalid = FALSE; 622 LeaveCriticalSection(&This->time_cs); 623 return hr; 624 } 625 626 static const IMediaSeekingVtbl IMediaSeekingPassThru_Vtbl = 627 { 628 MediaSeekingPassThru_QueryInterface, 629 MediaSeekingPassThru_AddRef, 630 MediaSeekingPassThru_Release, 631 MediaSeekingPassThru_GetCapabilities, 632 MediaSeekingPassThru_CheckCapabilities, 633 MediaSeekingPassThru_IsFormatSupported, 634 MediaSeekingPassThru_QueryPreferredFormat, 635 MediaSeekingPassThru_GetTimeFormat, 636 MediaSeekingPassThru_IsUsingTimeFormat, 637 MediaSeekingPassThru_SetTimeFormat, 638 MediaSeekingPassThru_GetDuration, 639 MediaSeekingPassThru_GetStopPosition, 640 MediaSeekingPassThru_GetCurrentPosition, 641 MediaSeekingPassThru_ConvertTimeFormat, 642 MediaSeekingPassThru_SetPositions, 643 MediaSeekingPassThru_GetPositions, 644 MediaSeekingPassThru_GetAvailable, 645 MediaSeekingPassThru_SetRate, 646 MediaSeekingPassThru_GetRate, 647 MediaSeekingPassThru_GetPreroll 648 }; 649 650 static HRESULT WINAPI MediaPositionPassThru_QueryInterface(IMediaPosition *iface, REFIID riid, LPVOID *ppvObj) 651 { 652 PassThruImpl *This = impl_from_IMediaPosition(iface); 653 654 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj); 655 656 return SeekOuter_QueryInterface(This, riid, ppvObj); 657 } 658 659 static ULONG WINAPI MediaPositionPassThru_AddRef(IMediaPosition *iface) 660 { 661 PassThruImpl *This = impl_from_IMediaPosition(iface); 662 663 TRACE("(%p/%p)->()\n", iface, This); 664 665 return SeekOuter_AddRef(This); 666 } 667 668 static ULONG WINAPI MediaPositionPassThru_Release(IMediaPosition *iface) 669 { 670 PassThruImpl *This = impl_from_IMediaPosition(iface); 671 672 TRACE("(%p/%p)->()\n", iface, This); 673 674 return SeekOuter_Release(This); 675 } 676 677 static HRESULT WINAPI MediaPositionPassThru_GetTypeInfoCount(IMediaPosition *iface, UINT*pctinfo) 678 { 679 PassThruImpl *This = impl_from_IMediaPosition(iface); 680 681 return BaseDispatchImpl_GetTypeInfoCount(&This->baseDispatch, pctinfo); 682 } 683 684 static HRESULT WINAPI MediaPositionPassThru_GetTypeInfo(IMediaPosition *iface, UINT iTInfo, LCID lcid, ITypeInfo**ppTInfo) 685 { 686 PassThruImpl *This = impl_from_IMediaPosition(iface); 687 688 return BaseDispatchImpl_GetTypeInfo(&This->baseDispatch, &IID_NULL, iTInfo, lcid, ppTInfo); 689 } 690 691 static HRESULT WINAPI MediaPositionPassThru_GetIDsOfNames(IMediaPosition *iface, REFIID riid, LPOLESTR*rgszNames, UINT cNames, LCID lcid, DISPID*rgDispId) 692 { 693 PassThruImpl *This = impl_from_IMediaPosition(iface); 694 695 return BaseDispatchImpl_GetIDsOfNames(&This->baseDispatch, riid, rgszNames, cNames, lcid, rgDispId); 696 } 697 698 static HRESULT WINAPI MediaPositionPassThru_Invoke(IMediaPosition *iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS*pDispParams, VARIANT*pVarResult, EXCEPINFO*pExepInfo, UINT*puArgErr) 699 { 700 PassThruImpl *This = impl_from_IMediaPosition(iface); 701 HRESULT hr = S_OK; 702 ITypeInfo *pTypeInfo; 703 704 hr = BaseDispatchImpl_GetTypeInfo(&This->baseDispatch, riid, 1, lcid, &pTypeInfo); 705 if (SUCCEEDED(hr)) 706 { 707 hr = ITypeInfo_Invoke(pTypeInfo, &This->IMediaPosition_iface, dispIdMember, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr); 708 ITypeInfo_Release(pTypeInfo); 709 } 710 711 return hr; 712 } 713 714 static HRESULT WINAPI MediaPositionPassThru_get_Duration(IMediaPosition *iface, REFTIME *plength) 715 { 716 PassThruImpl *This = impl_from_IMediaPosition(iface); 717 IMediaPosition *pos; 718 HRESULT hr; 719 720 TRACE("(%p)\n", plength); 721 722 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos); 723 if (SUCCEEDED(hr)) { 724 hr = IMediaPosition_get_Duration(pos, plength); 725 IMediaPosition_Release(pos); 726 } 727 else 728 return E_NOTIMPL; 729 return hr; 730 } 731 732 static HRESULT WINAPI MediaPositionPassThru_put_CurrentPosition(IMediaPosition *iface, REFTIME llTime) 733 { 734 PassThruImpl *This = impl_from_IMediaPosition(iface); 735 IMediaPosition *pos; 736 HRESULT hr; 737 738 TRACE("(%s)\n", wine_dbgstr_longlong(llTime)); 739 740 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos); 741 if (SUCCEEDED(hr)) { 742 hr = IMediaPosition_put_CurrentPosition(pos, llTime); 743 IMediaPosition_Release(pos); 744 } 745 else 746 return E_NOTIMPL; 747 return hr; 748 } 749 750 static HRESULT WINAPI MediaPositionPassThru_get_CurrentPosition(IMediaPosition *iface, REFTIME *pllTime) 751 { 752 PassThruImpl *This = impl_from_IMediaPosition(iface); 753 IMediaPosition *pos; 754 HRESULT hr; 755 756 TRACE("(%p)\n", pllTime); 757 758 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos); 759 if (SUCCEEDED(hr)) { 760 hr = IMediaPosition_get_CurrentPosition(pos, pllTime); 761 IMediaPosition_Release(pos); 762 } 763 else 764 return E_NOTIMPL; 765 return hr; 766 } 767 768 static HRESULT WINAPI MediaPositionPassThru_get_StopTime(IMediaPosition *iface, REFTIME *pllTime) 769 { 770 PassThruImpl *This = impl_from_IMediaPosition(iface); 771 IMediaPosition *pos; 772 HRESULT hr; 773 774 TRACE("(%p)\n", pllTime); 775 776 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos); 777 if (SUCCEEDED(hr)) { 778 hr = IMediaPosition_get_StopTime(pos, pllTime); 779 IMediaPosition_Release(pos); 780 } 781 else 782 return E_NOTIMPL; 783 return hr; 784 } 785 786 static HRESULT WINAPI MediaPositionPassThru_put_StopTime(IMediaPosition *iface, REFTIME llTime) 787 { 788 PassThruImpl *This = impl_from_IMediaPosition(iface); 789 IMediaPosition *pos; 790 HRESULT hr; 791 792 TRACE("(%s)\n", wine_dbgstr_longlong(llTime)); 793 794 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos); 795 if (SUCCEEDED(hr)) { 796 hr = IMediaPosition_put_StopTime(pos, llTime); 797 IMediaPosition_Release(pos); 798 } 799 else 800 return E_NOTIMPL; 801 return hr; 802 } 803 804 static HRESULT WINAPI MediaPositionPassThru_get_PrerollTime(IMediaPosition *iface, REFTIME *pllTime) 805 { 806 PassThruImpl *This = impl_from_IMediaPosition(iface); 807 IMediaPosition *pos; 808 HRESULT hr; 809 810 TRACE("(%p)\n", pllTime); 811 812 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos); 813 if (SUCCEEDED(hr)) { 814 hr = IMediaPosition_get_PrerollTime(pos, pllTime); 815 IMediaPosition_Release(pos); 816 } 817 else 818 return E_NOTIMPL; 819 return hr; 820 } 821 822 static HRESULT WINAPI MediaPositionPassThru_put_PrerollTime(IMediaPosition *iface, REFTIME llTime) 823 { 824 PassThruImpl *This = impl_from_IMediaPosition(iface); 825 IMediaPosition *pos; 826 HRESULT hr; 827 828 TRACE("(%s)\n", wine_dbgstr_longlong(llTime)); 829 830 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos); 831 if (SUCCEEDED(hr)) { 832 hr = IMediaPosition_put_PrerollTime(pos, llTime); 833 IMediaPosition_Release(pos); 834 } 835 else 836 return E_NOTIMPL; 837 return hr; 838 } 839 840 static HRESULT WINAPI MediaPositionPassThru_put_Rate(IMediaPosition *iface, double dRate) 841 { 842 PassThruImpl *This = impl_from_IMediaPosition(iface); 843 IMediaPosition *pos; 844 HRESULT hr; 845 846 TRACE("(%f)\n", dRate); 847 848 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos); 849 if (SUCCEEDED(hr)) { 850 hr = IMediaPosition_put_Rate(pos, dRate); 851 IMediaPosition_Release(pos); 852 } 853 else 854 return E_NOTIMPL; 855 return hr; 856 } 857 858 static HRESULT WINAPI MediaPositionPassThru_get_Rate(IMediaPosition *iface, double *pdRate) 859 { 860 PassThruImpl *This = impl_from_IMediaPosition(iface); 861 IMediaPosition *pos; 862 HRESULT hr; 863 864 TRACE("(%p)\n", pdRate); 865 866 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos); 867 if (SUCCEEDED(hr)) { 868 hr = IMediaPosition_get_Rate(pos, pdRate); 869 IMediaPosition_Release(pos); 870 } 871 else 872 return E_NOTIMPL; 873 return hr; 874 } 875 876 static HRESULT WINAPI MediaPositionPassThru_CanSeekForward(IMediaPosition *iface, LONG *pCanSeekForward) 877 { 878 PassThruImpl *This = impl_from_IMediaPosition(iface); 879 IMediaPosition *pos; 880 HRESULT hr; 881 882 TRACE("(%p)\n", pCanSeekForward); 883 884 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos); 885 if (SUCCEEDED(hr)) { 886 hr = IMediaPosition_CanSeekForward(pos, pCanSeekForward); 887 IMediaPosition_Release(pos); 888 } 889 else 890 return E_NOTIMPL; 891 return hr; 892 } 893 894 static HRESULT WINAPI MediaPositionPassThru_CanSeekBackward(IMediaPosition *iface, LONG *pCanSeekBackward) 895 { 896 PassThruImpl *This = impl_from_IMediaPosition(iface); 897 IMediaPosition *pos; 898 HRESULT hr; 899 900 TRACE("(%p)\n", pCanSeekBackward); 901 902 hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos); 903 if (SUCCEEDED(hr)) { 904 hr = IMediaPosition_CanSeekBackward(pos, pCanSeekBackward); 905 IMediaPosition_Release(pos); 906 } 907 else 908 return E_NOTIMPL; 909 return hr; 910 } 911 912 static const IMediaPositionVtbl IMediaPositionPassThru_Vtbl = 913 { 914 MediaPositionPassThru_QueryInterface, 915 MediaPositionPassThru_AddRef, 916 MediaPositionPassThru_Release, 917 MediaPositionPassThru_GetTypeInfoCount, 918 MediaPositionPassThru_GetTypeInfo, 919 MediaPositionPassThru_GetIDsOfNames, 920 MediaPositionPassThru_Invoke, 921 MediaPositionPassThru_get_Duration, 922 MediaPositionPassThru_put_CurrentPosition, 923 MediaPositionPassThru_get_CurrentPosition, 924 MediaPositionPassThru_get_StopTime, 925 MediaPositionPassThru_put_StopTime, 926 MediaPositionPassThru_get_PrerollTime, 927 MediaPositionPassThru_put_PrerollTime, 928 MediaPositionPassThru_put_Rate, 929 MediaPositionPassThru_get_Rate, 930 MediaPositionPassThru_CanSeekForward, 931 MediaPositionPassThru_CanSeekBackward 932 }; 933