Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1331 lines
27 KiB

  1. //
  2. // fpunit.cpp
  3. //
  4. #include "stdafx.h"
  5. #include "fpunit.h"
  6. #include "pbfilter.h"
  7. #include "vfwmsgs.h"
  8. //
  9. // The unit filter name
  10. //
  11. WCHAR g_bstrUnitFilterName[] = L"PlaybackUnitSource";
  12. WCHAR g_bstrUnitBridgeFilterName[] = L"PlaybackBridgeFilter";
  13. CPlaybackUnit::CPlaybackUnit()
  14. :m_pIGraphBuilder(NULL),
  15. m_hGraphEventHandle(NULL),
  16. m_pBridgeFilter(NULL),
  17. m_pSourceFilter(NULL)
  18. {
  19. LOG((MSP_TRACE, "CPlaybackUnit::CPlaybackUnit[%p] - enter. ", this));
  20. LOG((MSP_TRACE, "CPlaybackUnit::CPlaybackUnit - exit"));
  21. }
  22. CPlaybackUnit::~CPlaybackUnit()
  23. {
  24. LOG((MSP_TRACE, "CPlaybackUnit::~CPlaybackUnit[%p] - enter. ", this));
  25. LOG((MSP_TRACE, "CPlaybackUnit::~CPlaybackUnit - exit"));
  26. }
  27. //
  28. // --- Public members ---
  29. //
  30. /*++
  31. Inititalize the playback unit
  32. try to create the graph builder, initialize critical section,
  33. rgisters for the graph events
  34. --*/
  35. HRESULT CPlaybackUnit::Initialize(
  36. )
  37. {
  38. LOG((MSP_TRACE, "CPlaybackUnit::Initialize[%p] - enter. ", this));
  39. //
  40. // initialize should only be called once. it it is not, there is a bug in
  41. // our code
  42. //
  43. if (NULL != m_pIGraphBuilder)
  44. {
  45. LOG((MSP_ERROR, "CPlaybackUnit::Initialize - already initialized"));
  46. TM_ASSERT(FALSE);
  47. return E_UNEXPECTED;
  48. }
  49. //
  50. // attempt to initialize critical section
  51. //
  52. BOOL bCSInitSuccess = InitializeCriticalSectionAndSpinCount(&m_CriticalSection, 0);
  53. if (!bCSInitSuccess)
  54. {
  55. LOG((MSP_ERROR,
  56. "CPlaybackUnit::Initialize - failed to initialize critical section. LastError=%ld",
  57. GetLastError()));
  58. return E_OUTOFMEMORY;
  59. }
  60. //
  61. // Create filter graph
  62. //
  63. HRESULT hr = CoCreateInstance(
  64. CLSID_FilterGraph,
  65. NULL,
  66. CLSCTX_INPROC_SERVER,
  67. IID_IGraphBuilder,
  68. (void **) &m_pIGraphBuilder
  69. );
  70. if (FAILED(hr))
  71. {
  72. LOG((MSP_ERROR, "CPlaybackUnit::Initialize - failed to create filter graph. Returns 0x%08x", hr));
  73. DeleteCriticalSection(&m_CriticalSection);
  74. return hr;
  75. }
  76. //
  77. // Register for filter graph events
  78. //
  79. IMediaEvent *pMediaEvent = NULL;
  80. hr = m_pIGraphBuilder->QueryInterface(IID_IMediaEvent, (void**)&pMediaEvent);
  81. if (FAILED(hr))
  82. {
  83. LOG((MSP_ERROR, "CPlaybackUnit::HandleGraphEvent - failed to qi graph for IMediaEvent, Returns 0x%08x", hr));
  84. // Clean-up
  85. m_pIGraphBuilder->Release();
  86. m_pIGraphBuilder = NULL;
  87. DeleteCriticalSection(&m_CriticalSection);
  88. return hr;
  89. }
  90. //
  91. // Get filter graph's event
  92. //
  93. HANDLE hEvent = NULL;
  94. hr = pMediaEvent->GetEventHandle((OAEVENT*)&hEvent);
  95. //
  96. // Clean-up
  97. //
  98. pMediaEvent->Release();
  99. pMediaEvent = NULL;
  100. if (FAILED(hr))
  101. {
  102. LOG((MSP_ERROR, "CPlaybackUnit::HandleGraphEvent - failed to get graph's event. Returns 0x%08x", hr));
  103. // Clean-up
  104. m_pIGraphBuilder->Release();
  105. m_pIGraphBuilder = NULL;
  106. DeleteCriticalSection(&m_CriticalSection);
  107. return hr;
  108. }
  109. //
  110. // Register for the graph event
  111. //
  112. BOOL fSuccess = RegisterWaitForSingleObject(
  113. &m_hGraphEventHandle, // pointer to the returned handle
  114. hEvent, // the event handle to wait for.
  115. CPlaybackUnit::HandleGraphEvent, // the callback function.
  116. this, // the context for the callback.
  117. INFINITE, // wait forever.
  118. WT_EXECUTEDEFAULT |
  119. WT_EXECUTEINWAITTHREAD // use the wait thread to call the callback.
  120. );
  121. if ( ! fSuccess )
  122. {
  123. LOG((MSP_ERROR, "CPlaybackUnit::HandleGraphEvent - failed to register wait event", hr));
  124. // Clean-up
  125. m_pIGraphBuilder->Release();
  126. m_pIGraphBuilder = NULL;
  127. DeleteCriticalSection(&m_CriticalSection);
  128. return hr;
  129. }
  130. LOG((MSP_TRACE, "CPlaybackUnit::Initialize - exit"));
  131. return S_OK;
  132. }
  133. //
  134. // SetupFromFile try to create a filter graph and
  135. // the bridge filter with input pins based on the file
  136. //
  137. HRESULT CPlaybackUnit::SetupFromFile(
  138. IN BSTR bstrFileName
  139. )
  140. {
  141. LOG((MSP_TRACE, "CPlaybackUnit::SetupFromFile[%p] - enter", this));
  142. //
  143. // Check arguments
  144. //
  145. if (IsBadStringPtr(bstrFileName, -1))
  146. {
  147. LOG((MSP_ERROR, "CPlaybackUnit::SetupFromFile - bad file name passed in"));
  148. TM_ASSERT(FALSE);
  149. return E_UNEXPECTED;
  150. }
  151. //
  152. // Make sure we have been initialized
  153. //
  154. if (NULL == m_pIGraphBuilder)
  155. {
  156. LOG((MSP_ERROR, "CPlaybackUnit::SetupFromFile - not yet initialized."));
  157. TM_ASSERT(FALSE);
  158. return E_UNEXPECTED;
  159. }
  160. //
  161. // lock before accessing data members
  162. //
  163. CCSLock Lock(&m_CriticalSection);
  164. //
  165. // Make sure the graph is stopped
  166. //
  167. HRESULT hr = IsGraphInState( State_Stopped );
  168. if( FAILED(hr) )
  169. {
  170. //
  171. // Stop the graph
  172. //
  173. hr = Stop();
  174. if( FAILED(hr) )
  175. {
  176. LOG((MSP_ERROR,
  177. "CPlaybackUnit::SetupFromFile - "
  178. "graph cannot be stop. Returns 0x%08x", hr));
  179. return hr;
  180. }
  181. }
  182. //
  183. // Remove the existing source filter
  184. // if we have one
  185. //
  186. if( m_pSourceFilter != NULL)
  187. {
  188. hr = RemoveSourceFilter();
  189. if( FAILED(hr) )
  190. {
  191. LOG((MSP_ERROR,
  192. "CPlaybackUnit::SetupFromFile - "
  193. "RemoveSourceFilter failed. Returns 0x%08x", hr));
  194. return hr;
  195. }
  196. }
  197. //
  198. // Add the source filter to the filter graph
  199. //
  200. hr = m_pIGraphBuilder->AddSourceFilter(
  201. bstrFileName,
  202. g_bstrUnitFilterName,
  203. &m_pSourceFilter
  204. );
  205. if( FAILED(hr) )
  206. {
  207. LOG((MSP_ERROR,
  208. "CPlaybackUnit::SetupFromFile - "
  209. "AddSourceFilter failed. Returns 0x%08x", hr));
  210. return hr;
  211. }
  212. //
  213. // Get the source pin
  214. //
  215. IPin* pSourcePin = NULL;
  216. hr = GetSourcePin( &pSourcePin );
  217. if( FAILED(hr) )
  218. {
  219. // Clean-up
  220. RemoveSourceFilter();
  221. LOG((MSP_ERROR,
  222. "CPlaybackUnit::SetupFromFile - "
  223. "GetSourcePin failed. Returns 0x%08x", hr));
  224. return hr;
  225. }
  226. //
  227. // We add bridge filters to the graph
  228. //
  229. hr = AddBridgeFilter();
  230. if( FAILED(hr) )
  231. {
  232. // Clean-up
  233. pSourcePin->Release();
  234. RemoveSourceFilter();
  235. LOG((MSP_ERROR,
  236. "CPlaybackUnit::SetupFromFile - "
  237. "AddBridgeFilters failed. Returns 0x%08x", hr));
  238. return hr;
  239. }
  240. //
  241. // Let graph to render
  242. //
  243. hr = m_pIGraphBuilder->Render( pSourcePin );
  244. if( FAILED(hr) )
  245. {
  246. // Clean-up
  247. pSourcePin->Release();
  248. RemoveSourceFilter();
  249. LOG((MSP_ERROR,
  250. "CPlaybackUnit::SetupFromFile - "
  251. "AddBridgeFilters failed. Returns 0x%08x", hr));
  252. return hr;
  253. }
  254. //
  255. // Clean-up
  256. //
  257. pSourcePin->Release();
  258. pSourcePin = NULL;
  259. LOG((MSP_TRACE, "CPlaybackUnit::SetupFromFile - finished"));
  260. return S_OK;
  261. }
  262. HRESULT CPlaybackUnit::GetState(OAFilterState *pGraphState)
  263. {
  264. LOG((MSP_TRACE, "CPlaybackUnit::GetState[%p] - enter", this));
  265. //
  266. // make sure we have been initialized.
  267. //
  268. if (NULL == m_pIGraphBuilder)
  269. {
  270. LOG((MSP_ERROR, "CPlaybackUnit::GetState - not yet initialized."));
  271. TM_ASSERT(FALSE);
  272. return E_UNEXPECTED;
  273. }
  274. //
  275. // get media control interface so we change state
  276. //
  277. IMediaControl *pIMediaControl = NULL;
  278. {
  279. //
  280. // will be accessing data members -- in a lock
  281. //
  282. CCSLock Lock(&m_CriticalSection);
  283. HRESULT hr = m_pIGraphBuilder->QueryInterface(
  284. IID_IMediaControl,
  285. (void**)&pIMediaControl
  286. );
  287. if (FAILED(hr))
  288. {
  289. LOG((MSP_ERROR, "CPlaybackUnit::ChangeState - failed to qi for IMediaControl. hr = %lx", hr));
  290. return hr;
  291. }
  292. }
  293. //
  294. // try to get state outside the lock
  295. //
  296. OAFilterState GraphState = (OAFilterState) -1;
  297. HRESULT hr = pIMediaControl->GetState(10, &GraphState);
  298. pIMediaControl->Release();
  299. pIMediaControl = NULL;
  300. //
  301. // did we succeed at all?
  302. //
  303. if (FAILED(hr))
  304. {
  305. LOG((MSP_ERROR,
  306. "CPlaybackUnit::ChangeState - failed to get state. hr = %lx", hr));
  307. return hr;
  308. }
  309. //
  310. // is the state transition still in progress?
  311. //
  312. if (VFW_S_STATE_INTERMEDIATE == hr)
  313. {
  314. LOG((MSP_WARN,
  315. "CPlaybackUnit::ChangeState - state transition in progress. "
  316. "returNing VFW_S_STATE_INTERMEDIATE"));
  317. //
  318. // continue -- the state is what we are transitioning to
  319. //
  320. }
  321. //
  322. // log if we got VFW_S_CANT_CUE
  323. //
  324. if (VFW_S_CANT_CUE == hr)
  325. {
  326. LOG((MSP_WARN,
  327. "CPlaybackUnit::GetState - fg returned VFW_S_CANT_CUE"));
  328. //
  329. // continue -- we still should have received a valid state
  330. //
  331. }
  332. //
  333. // log the state
  334. //
  335. switch (GraphState)
  336. {
  337. case State_Stopped:
  338. LOG((MSP_TRACE, "CPlaybackUnit::GetState - State_Stopped"));
  339. *pGraphState = GraphState;
  340. break;
  341. case State_Running:
  342. LOG((MSP_TRACE, "CPlaybackUnit::GetState - State_Running"));
  343. *pGraphState = GraphState;
  344. break;
  345. case State_Paused:
  346. LOG((MSP_TRACE, "CPlaybackUnit::GetState- State_Paused"));
  347. *pGraphState = GraphState;
  348. break;
  349. default:
  350. LOG((MSP_TRACE, "CPlaybackUnit::GetState- unknown state %ld", GraphState));
  351. hr = E_FAIL;
  352. break;
  353. }
  354. LOG((MSP_(hr), "CPlaybackUnit::GetState - finish. hr = %lx", hr));
  355. return hr;
  356. }
  357. VOID CPlaybackUnit::HandleGraphEvent(
  358. IN VOID *pContext,
  359. IN BOOLEAN bReason)
  360. {
  361. LOG((MSP_TRACE, "CPlaybackUnit::HandleGraphEvent - enter FT:[%p].", pContext));
  362. //
  363. // get recording unit pointer out of context
  364. //
  365. CPlaybackUnit *pPlaybackUnit =
  366. static_cast<CPlaybackUnit*>(pContext);
  367. if (IsBadReadPtr(pPlaybackUnit, sizeof(CPlaybackUnit)) )
  368. {
  369. LOG((MSP_ERROR, "CPlaybackUnit::HandleGraphEvent - bad context"));
  370. return;
  371. }
  372. //
  373. // the graph was not initialized. something went wrong.
  374. //
  375. if (NULL == pPlaybackUnit->m_pIGraphBuilder)
  376. {
  377. LOG((MSP_ERROR, "CPlaybackUnit::HandleGraphEvent - not initialized. filter graph null"));
  378. return;
  379. }
  380. //
  381. // lock the object (just in case the object pointer is bad, do inside try/catch
  382. //
  383. try
  384. {
  385. EnterCriticalSection(&(pPlaybackUnit->m_CriticalSection));
  386. }
  387. catch(...)
  388. {
  389. LOG((MSP_ERROR, "CPlaybackUnit::HandleGraphEvent - exception accessing critical section"));
  390. return;
  391. }
  392. //
  393. // get the media event interface so we can retrieve the event
  394. //
  395. IMediaEvent *pMediaEvent = NULL;
  396. HRESULT hr =
  397. pPlaybackUnit->m_pIGraphBuilder->QueryInterface(IID_IMediaEvent,
  398. (void**)&pMediaEvent);
  399. if (FAILED(hr))
  400. {
  401. LOG((MSP_ERROR, "CPlaybackUnit::HandleGraphEvent - failed to qi graph for IMediaEvent"));
  402. LeaveCriticalSection(&(pPlaybackUnit->m_CriticalSection));
  403. return;
  404. }
  405. //
  406. // while holding critical section, get the terminal on which to fire the event
  407. //
  408. //CFileRecordingTerminal *pRecordingterminal = pPlaybackUnit->m_pRecordingTerminal;
  409. //pRecordingterminal->AddRef();
  410. //
  411. // no longer need to access data members, release critical section
  412. //
  413. LeaveCriticalSection(&(pPlaybackUnit->m_CriticalSection));
  414. //
  415. // get the actual event
  416. //
  417. long lEventCode = 0;
  418. LONG_PTR lParam1 = 0;
  419. LONG_PTR lParam2 = 0;
  420. hr = pMediaEvent->GetEvent(&lEventCode, &lParam1, &lParam2, 0);
  421. if (FAILED(hr))
  422. {
  423. LOG((MSP_ERROR, "CPlaybackUnit::HandleGraphEvent - failed to get the event. hr = %lx", hr));
  424. // Clean-up
  425. pMediaEvent->FreeEventParams(lEventCode, lParam1, lParam2);
  426. pMediaEvent->Release();
  427. pMediaEvent = NULL;
  428. return;
  429. }
  430. LOG((MSP_EVENT, "CPlaybackUnit::HandleGraphEvent - received event code:[0x%lx] param1:[%p] param2:[%p]",
  431. lEventCode, lParam1, lParam2));
  432. //
  433. // ask file terminal to handle the event
  434. //
  435. // Clean-up
  436. pMediaEvent->FreeEventParams(lEventCode, lParam1, lParam2);
  437. pMediaEvent->Release();
  438. pMediaEvent = NULL;
  439. if (FAILED(hr))
  440. {
  441. LOG((MSP_ERROR,
  442. "CPlaybackUnit::HandleGraphEvent - failed to fire event on the terminal. hr = %lx",
  443. hr));
  444. return;
  445. }
  446. }
  447. HRESULT CPlaybackUnit::IsGraphInState(
  448. IN OAFilterState State
  449. )
  450. {
  451. LOG((MSP_TRACE, "CPlaybackUnit::IsGraphInState[%p] - enter", this));
  452. //
  453. // Get the graph state
  454. //
  455. OAFilterState DSState;
  456. HRESULT hr = GetState(&DSState);
  457. //
  458. // is the state transition still in progress?
  459. //
  460. if (VFW_S_STATE_INTERMEDIATE == hr)
  461. {
  462. LOG((MSP_ERROR, "CPlaybackUnit::IsGraphInState - exit"
  463. " graph is not yet initialized. Returns TAPI_E_WRONG_STATE"));
  464. return TAPI_E_WRONG_STATE;
  465. }
  466. //
  467. // is the return anything other than S_OK
  468. //
  469. if (hr != S_OK)
  470. {
  471. LOG((MSP_ERROR,
  472. "CPlaybackUnit::IsGraphInState - exit "
  473. "failed to get state of the filter graph. Returns 0x%08x", hr));
  474. return hr;
  475. }
  476. if (State != DSState)
  477. {
  478. LOG((MSP_ERROR,
  479. "CPlaybackUnit::IsGraphInState - exit "
  480. "other state then we asked for. Returns TAPI_E_WRONG_STATE"));
  481. return TAPI_E_WRONG_STATE;
  482. }
  483. LOG((MSP_(hr), "CPlaybackUnit::IsGraphInState - exit. Returns 0x%08x", hr));
  484. return hr;
  485. }
  486. /*++
  487. Renoves the source filter from the filter graph and
  488. set the source filter on NULL.
  489. --*/
  490. HRESULT CPlaybackUnit::RemoveSourceFilter()
  491. {
  492. LOG((MSP_TRACE, "CPlaybackUnit::RemoveSourceFilter[%p] - enter", this));
  493. //
  494. // Do we have a source filter?
  495. //
  496. if( m_pSourceFilter == NULL )
  497. {
  498. LOG((MSP_TRACE, "CPlaybackUnit::ChangeState - "
  499. "we have a NULL source filter already. Returns S_OK"));
  500. return S_OK;
  501. }
  502. //
  503. // Get the IFilterGraph interface
  504. //
  505. IFilterGraph* pFilterGraph = NULL;
  506. HRESULT hr = m_pIGraphBuilder->QueryInterface(
  507. IID_IFilterGraph,
  508. (void**)&pFilterGraph
  509. );
  510. if( FAILED(hr) )
  511. {
  512. LOG((MSP_ERROR,
  513. "CPlaybackUnit::RemoveSourceFilter - "
  514. "QI for IFilterGraph failed. Returns 0x%08x", hr));
  515. return hr;
  516. }
  517. //
  518. // Remove the source filter from the graph
  519. //
  520. pFilterGraph->RemoveFilter( m_pSourceFilter );
  521. //
  522. // Clean-up the source filter anyway
  523. //
  524. m_pSourceFilter->Release();
  525. m_pSourceFilter = NULL;
  526. // Clean-up
  527. pFilterGraph->Release();
  528. pFilterGraph = NULL;
  529. LOG((MSP_(hr), "CPlaybackUnit::AddSourceFilter - exit. Returns 0x%08x", hr));
  530. return hr;
  531. }
  532. /*++
  533. Removes the bridge filter from the filter graph and
  534. set the bridge filter on NULL.
  535. --*/
  536. HRESULT CPlaybackUnit::RemoveBridgeFilter(
  537. )
  538. {
  539. LOG((MSP_TRACE, "CPlaybackUnit::RemoveBridgeFilter[%p] - enter", this));
  540. //
  541. // Do we have a bridge filter?
  542. //
  543. if( m_pBridgeFilter == NULL )
  544. {
  545. LOG((MSP_TRACE, "CPlaybackUnit::RemoveBridgeFilter - "
  546. "we have a NULL bridge filter already. Returns S_OK"));
  547. return S_OK;
  548. }
  549. //
  550. // Get the IFilterGraph interface
  551. //
  552. IFilterGraph* pFilterGraph = NULL;
  553. HRESULT hr = m_pIGraphBuilder->QueryInterface(
  554. IID_IFilterGraph,
  555. (void**)&pFilterGraph
  556. );
  557. if( FAILED(hr) )
  558. {
  559. LOG((MSP_ERROR,
  560. "CPlaybackUnit::RemoveBridgeFilter - "
  561. "QI for IFilterGraph failed. Returns 0x%08x", hr));
  562. return hr;
  563. }
  564. //
  565. // Remove the bridge filter from the graph
  566. //
  567. pFilterGraph->RemoveFilter( m_pBridgeFilter );
  568. //
  569. // Clean-up the bridge filter anyway
  570. //
  571. m_pBridgeFilter = NULL;
  572. // Clean-up
  573. pFilterGraph->Release();
  574. pFilterGraph = NULL;
  575. LOG((MSP_(hr), "CPlaybackUnit::RemoveBridgeFilter - exit. Returns 0x%08x", hr));
  576. return hr;
  577. }
  578. HRESULT CPlaybackUnit::GetSourcePin(
  579. OUT IPin** ppPin
  580. )
  581. {
  582. LOG((MSP_TRACE, "CPlaybackUnit::GetSourcePin[%p] - enter", this));
  583. TM_ASSERT( m_pSourceFilter );
  584. //
  585. // Reset the value
  586. //
  587. *ppPin = NULL;
  588. //
  589. // Get the in enumeration
  590. //
  591. IEnumPins* pEnumPins = NULL;
  592. HRESULT hr = m_pSourceFilter->EnumPins( &pEnumPins );
  593. if( FAILED(hr) )
  594. {
  595. LOG((MSP_ERROR,
  596. "CPlaybackUnit::GetSourcePin - exit "
  597. "EnumPins failed. Returns 0x%08x", hr));
  598. return hr;
  599. }
  600. //
  601. // Get the first pin
  602. //
  603. IPin* pPin = NULL;
  604. ULONG uFetched = 0;
  605. hr = pEnumPins->Next(1, &pPin, &uFetched );
  606. //
  607. // Release the enumeration
  608. //
  609. pEnumPins->Release();
  610. pEnumPins = NULL;
  611. if( hr != S_OK )
  612. {
  613. LOG((MSP_ERROR,
  614. "CPlaybackUnit::GetSourcePin - exit "
  615. "we don't have a pin. Returns E_FAIL"));
  616. return E_FAIL;
  617. }
  618. //
  619. // Return the pin
  620. //
  621. *ppPin = pPin;
  622. LOG((MSP_TRACE, "CPlaybackUnit::GetSourcePin - exit S_OK"));
  623. return S_OK;
  624. }
  625. HRESULT CPlaybackUnit::AddBridgeFilter(
  626. )
  627. {
  628. LOG((MSP_TRACE, "CPlaybackUnit::AddBridgeFilter[%p] - enter", this));
  629. if( m_pBridgeFilter )
  630. {
  631. LOG((MSP_TRACE, "CPlaybackUnit::AddBridgeFilter - "
  632. "we already have a bridge filter. Return S_OK"));
  633. return S_OK;
  634. }
  635. //
  636. // Create the new bridge filter
  637. //
  638. m_pBridgeFilter = new CPBFilter();
  639. if( m_pBridgeFilter == NULL)
  640. {
  641. LOG((MSP_ERROR,
  642. "CPlaybackUnit::AddBridgeFilter - exit "
  643. "new allocation for CPBFilter failed. Returns E_OUTOFMEMORY"));
  644. return E_OUTOFMEMORY;
  645. }
  646. //
  647. // Initialize the bridge filter
  648. //
  649. HRESULT hr = m_pBridgeFilter->Initialize( this );
  650. if( FAILED(hr) )
  651. {
  652. // Clean-up
  653. delete m_pBridgeFilter;
  654. m_pBridgeFilter = NULL;
  655. LOG((MSP_ERROR,
  656. "CPlaybackUnit::AddBridgeFilter - exit "
  657. "initialize failed. Returns 0x%08x", hr));
  658. return hr;
  659. }
  660. //
  661. // Add this bridge filter to the graph
  662. //
  663. hr = m_pIGraphBuilder->AddFilter(
  664. m_pBridgeFilter,
  665. g_bstrUnitBridgeFilterName
  666. );
  667. if( FAILED(hr) )
  668. {
  669. // Clean-up
  670. delete m_pBridgeFilter;
  671. m_pBridgeFilter = NULL;
  672. LOG((MSP_ERROR,
  673. "CPlaybackUnit::AddBridgeFilter - exit "
  674. "Add filter failed. Returns 0x%08x", hr));
  675. return hr;
  676. }
  677. LOG((MSP_(hr), "CPlaybackUnit::AddBridgeFilter - exit. Returns 0x%08x", hr));
  678. return hr;
  679. }
  680. //
  681. // retrieve the media supported by the filter
  682. //
  683. HRESULT CPlaybackUnit::get_MediaTypes(
  684. OUT long* pMediaTypes
  685. )
  686. {
  687. LOG((MSP_TRACE, "CPlaybackUnit::get_MediaTypes[%p] - enter", this));
  688. TM_ASSERT( pMediaTypes != NULL );
  689. TM_ASSERT( m_pBridgeFilter != NULL );
  690. HRESULT hr = E_FAIL;
  691. //
  692. // lock before accessing data members
  693. //
  694. CCSLock Lock(&m_CriticalSection);
  695. //
  696. // Get the media types from the filter
  697. //
  698. hr = m_pBridgeFilter->get_MediaTypes( pMediaTypes );
  699. if( FAILED(hr) )
  700. {
  701. LOG((MSP_ERROR,
  702. "CPlaybackUnit::get_MediaTypes - exit "
  703. "get_MediaTypes failed. Returns 0x%08x", hr));
  704. return hr;
  705. }
  706. LOG((MSP_(hr), "CPlaybackUnit::get_MediaTypes - exit. Returns S_OK"));
  707. return S_OK;
  708. }
  709. HRESULT CPlaybackUnit::GetMediaPin(
  710. IN long nMediaType,
  711. IN int nIndex,
  712. OUT CPBPin** ppPin
  713. )
  714. {
  715. LOG((MSP_TRACE, "CPlaybackUnit::GetMediaPin[%p] - enter", this));
  716. TM_ASSERT( ppPin != NULL );
  717. TM_ASSERT( m_pBridgeFilter != NULL );
  718. HRESULT hr = E_FAIL;
  719. *ppPin = NULL;
  720. //
  721. // lock before accessing data members
  722. //
  723. CCSLock Lock(&m_CriticalSection);
  724. //
  725. // Get the media types from the filter
  726. //
  727. int nPins = m_pBridgeFilter->GetPinCount();
  728. int nMediaPin = 0;
  729. for(int nPin=0; nPin < nPins; nPin++)
  730. {
  731. CPBPin* pPin = static_cast<CPBPin*>(m_pBridgeFilter->GetPin(nPin));
  732. if( pPin )
  733. {
  734. long mt = 0;
  735. pPin->get_MediaType( &mt );
  736. if( (mt == nMediaType) && (nIndex == nMediaPin) )
  737. {
  738. *ppPin = pPin;
  739. hr = S_OK;
  740. break;
  741. }
  742. if( mt == nMediaType )
  743. {
  744. nMediaPin++;
  745. }
  746. }
  747. }
  748. LOG((MSP_(hr), "CPlaybackUnit::GetMediaPin - exit. Returns 0x%08x", hr));
  749. return hr;
  750. }
  751. ///////////////////////////////////////////////////////////////////////////////
  752. HRESULT CPlaybackUnit::ChangeState(OAFilterState DesiredState)
  753. {
  754. LOG((MSP_TRACE, "CPlaybackUnit::ChangeState[%p] - enter", this));
  755. //
  756. // make sure we have been initialized
  757. //
  758. if (NULL == m_pIGraphBuilder)
  759. {
  760. LOG((MSP_ERROR, "CPlaybackUnit::ChangeState - not yet initialized."));
  761. TM_ASSERT(FALSE);
  762. return E_UNEXPECTED;
  763. }
  764. //
  765. // check the current state first
  766. //
  767. OAFilterState GraphState;
  768. HRESULT hr = GetState(&GraphState);
  769. //
  770. // is the state transition still in progress?
  771. //
  772. if (VFW_S_STATE_INTERMEDIATE == hr)
  773. {
  774. LOG((MSP_WARN, "CPlaybackUnit::ChangeState - state transition in progress. returing TAPI_E_WRONG_STATE"));
  775. return TAPI_E_WRONG_STATE;
  776. }
  777. //
  778. // is the return anything other than S_OK
  779. //
  780. if (hr != S_OK)
  781. {
  782. LOG((MSP_ERROR,
  783. "CPlaybackUnit::ChangeState - failed to get state of the filter graph. hr = %lx",
  784. hr));
  785. return hr;
  786. }
  787. TM_ASSERT(hr == S_OK);
  788. //
  789. // nothing to do if we are already in that state
  790. //
  791. if (DesiredState == GraphState)
  792. {
  793. LOG((MSP_TRACE,
  794. "CPlaybackUnit::ChangeState - graph is already in state %ld. nothing to do.", DesiredState));
  795. return S_OK;
  796. }
  797. //
  798. // get media control interface so we change state
  799. //
  800. IMediaControl *pIMediaControl = NULL;
  801. {
  802. //
  803. // will be accessing data members -- in a lock
  804. //
  805. CCSLock Lock(&m_CriticalSection);
  806. hr = m_pIGraphBuilder->QueryInterface(IID_IMediaControl, (void**)&pIMediaControl);
  807. if (FAILED(hr))
  808. {
  809. LOG((MSP_ERROR, "CPlaybackUnit::ChangeState - failed to qi for IMediaControl. hr = %lx", hr));
  810. return hr;
  811. }
  812. }
  813. //
  814. // try to make state transition
  815. //
  816. switch (DesiredState)
  817. {
  818. case State_Stopped:
  819. LOG((MSP_TRACE, "CPlaybackUnit::ChangeState - stopping"));
  820. hr = pIMediaControl->Stop();
  821. break;
  822. case State_Running:
  823. LOG((MSP_TRACE, "CPlaybackUnit::ChangeState - starting"));
  824. hr = pIMediaControl->Run();
  825. break;
  826. case State_Paused:
  827. LOG((MSP_TRACE, "CPlaybackUnit::ChangeState - pausing"));
  828. hr = pIMediaControl->Pause();
  829. break;
  830. default:
  831. LOG((MSP_TRACE, "CPlaybackUnit::ChangeState - unknown state %ld", DesiredState));
  832. hr = E_INVALIDARG;
  833. break;
  834. }
  835. pIMediaControl->Release();
  836. pIMediaControl = NULL;
  837. if (FAILED(hr))
  838. {
  839. LOG((MSP_ERROR, "CPlaybackUnit::ChangeState - state change failed. hr = %lx", hr));
  840. return hr;
  841. }
  842. LOG((MSP_TRACE, "CPlaybackUnit::ChangeState - finish"));
  843. return S_OK;
  844. }
  845. ///////////////////////////////////////////////////////////////////////////////
  846. HRESULT CPlaybackUnit::Start()
  847. {
  848. LOG((MSP_TRACE, "CPlaybackUnit::Start[%p] - enter", this));
  849. HRESULT hr = ChangeState(State_Running);
  850. LOG((MSP_(hr), "CPlaybackUnit::Start - finish. hr = %lx", hr));
  851. return hr;
  852. }
  853. HRESULT CPlaybackUnit::Pause()
  854. {
  855. LOG((MSP_TRACE, "CPlaybackUnit::Pause[%p] - enter", this));
  856. HRESULT hr = ChangeState(State_Paused);
  857. LOG((MSP_(hr), "CPlaybackUnit::Pause - finish. hr = %lx", hr));
  858. return hr;
  859. }
  860. HRESULT CPlaybackUnit::Stop()
  861. {
  862. LOG((MSP_TRACE, "CPlaybackUnit::Stop[%p] - enter", this));
  863. HRESULT hr = ChangeState(State_Stopped);
  864. LOG((MSP_(hr), "CPlaybackUnit::Stop - finish. hr = %lx", hr));
  865. return hr;
  866. }
  867. HRESULT CPlaybackUnit::Shutdown()
  868. {
  869. //
  870. // if we don't have filter graph, we have not passed initialization
  871. //
  872. if (NULL == m_pIGraphBuilder)
  873. {
  874. LOG((MSP_TRACE, "CPlaybackUnit::Shutdown - not yet initialized. nothing to shut down"));
  875. return S_OK;
  876. }
  877. //
  878. // first of all, make sure the graph is stopped
  879. //
  880. HRESULT hr = Stop();
  881. if (FAILED(hr))
  882. {
  883. LOG((MSP_ERROR, "CPlaybackUnit::Shutdown - exit "
  884. "failed to stop filter graph, hr = 0x%08x", hr));
  885. return hr;
  886. }
  887. //
  888. // unregister wait event
  889. //
  890. BOOL bUnregisterResult = ::UnregisterWaitEx(m_hGraphEventHandle, (HANDLE)-1);
  891. m_hGraphEventHandle = NULL;
  892. if (!bUnregisterResult)
  893. {
  894. LOG((MSP_ERROR, "CPlaybackUnit::Shutdown - failed to unregisted even. continuing anyway"));
  895. }
  896. //
  897. // Remove the bridge filter
  898. //
  899. hr = RemoveBridgeFilter();
  900. if( FAILED(hr) )
  901. {
  902. LOG((MSP_ERROR, "CPlaybackUnit::Shutdown - exit "
  903. "RemoveBridgeFilter failed, hr = 0x%08x", hr));
  904. return hr;
  905. }
  906. //
  907. // Remove the source filter
  908. //
  909. hr = RemoveSourceFilter();
  910. if( FAILED(hr) )
  911. {
  912. LOG((MSP_ERROR, "CPlaybackUnit::Shutdown - exit "
  913. "RemoveSourceFilter failed, hr = 0x%08x", hr));
  914. return hr;
  915. }
  916. //
  917. // release filter graph
  918. //
  919. if( m_pIGraphBuilder != NULL )
  920. {
  921. m_pIGraphBuilder->Release();
  922. m_pIGraphBuilder = NULL;
  923. }
  924. //
  925. // no need to keep critical section around any longer -- no one should be
  926. // using this object anymore
  927. //
  928. DeleteCriticalSection(&m_CriticalSection);
  929. LOG((MSP_TRACE, "CPlaybackUnit::Shutdown - finished"));
  930. return S_OK;
  931. }
  932. // eof