Source code of Windows XP (NT5)
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.

696 lines
25 KiB

  1. //==========================================================================;
  2. //
  3. // playbackimpl.h : additional infrastructure to support implementing IMSVidPlayback
  4. // nicely from c++
  5. // Copyright (c) Microsoft Corporation 1999.
  6. //
  7. /////////////////////////////////////////////////////////////////////////////
  8. #pragma once
  9. #ifndef PLAYBACKIMPL_H
  10. #define PLAYBACKIMPL_H
  11. #include <math.h>
  12. #include "inputimpl.h"
  13. #include <uuids.h>
  14. namespace MSVideoControl {
  15. #define BACKWARDS_STEPPING 0
  16. const long nano_to_hundredths = 100000;
  17. template<class T, LPCGUID LibID, LPCGUID KSCategory, class MostDerivedInterface = IMSVidPlayback>
  18. class DECLSPEC_NOVTABLE IMSVidPlaybackImpl :
  19. public IMSVidInputDeviceImpl<T, LibID, KSCategory, MostDerivedInterface> {
  20. protected:
  21. bool m_fEnableResetOnStop;
  22. public:
  23. IMSVidPlaybackImpl():
  24. m_fEnableResetOnStop(false) {}
  25. virtual ~IMSVidPlaybackImpl() {}
  26. //-----------------------------------------------------------------------------------------
  27. // Name:
  28. //-----------------------------------------------------------------------------------------
  29. STDMETHOD(get_Length)(/*[out, retval]*/long *lLength){
  30. HRESULT hr = S_OK;
  31. LONGLONG tempval;
  32. PositionModeList curMode;
  33. try{
  34. // Checking args and init'ing interfaces
  35. if (!lLength){
  36. return E_POINTER;
  37. }
  38. if (!m_pGraph) {
  39. // graph not valid
  40. return ImplReportError(__uuidof(T), IDS_INVALID_STATE, __uuidof(IMSVidPlayback), HRESULT_FROM_WIN32(ERROR_INVALID_STATE));
  41. }
  42. // See if object supports IMediaSeeking
  43. PQMediaSeeking PQIMSeeking(m_pGraph);
  44. if(PQIMSeeking){
  45. // Find out what postion mode is being used
  46. hr = get_PositionMode(&curMode);
  47. if(FAILED(hr)){
  48. return hr;
  49. }
  50. hr = PQIMSeeking->GetDuration(&tempval);
  51. if(FAILED(hr)){
  52. return hr;
  53. }
  54. // If it is FrameMode no conversion needed
  55. if(curMode == FrameMode){
  56. *lLength = static_cast<long>(tempval);
  57. hr = S_OK;
  58. return hr;
  59. }
  60. // If it is TenthsSecondsMode need to be converted from 100 nanosecond units
  61. else if(curMode == TenthsSecondsMode){
  62. *lLength = static_cast<long>(tempval / nano_to_hundredths);
  63. hr = S_OK;
  64. return hr;
  65. }
  66. // If it is some other mode not supported by the vidctl
  67. else{
  68. return E_UNEXPECTED;
  69. }
  70. }
  71. // See if object supports IMediaPostion
  72. PQMediaPosition PQIMPos(m_pGraph);
  73. if(PQIMPos){
  74. // Get position
  75. double tempDub;
  76. hr = PQIMPos->get_CurrentPosition(&tempDub);
  77. // IMediaPostion only supports 100 Nanosecond units
  78. *lLength = static_cast<long>(tempDub / nano_to_hundredths);
  79. hr = S_OK;
  80. return hr;
  81. }
  82. // Could Not QI IMedia Seeking or Position
  83. return ImplReportError(__uuidof(T), IDS_E_CANTQI , __uuidof(IMSVidPlayback), E_NOINTERFACE);
  84. }
  85. catch(HRESULT hrTmp){
  86. // Something went bad, threw a HRESULT
  87. return ImplReportError(__uuidof(T), IDS_INVALID_STATE , __uuidof(IMSVidPlayback), hrTmp);
  88. }
  89. catch(...){
  90. // Something went bad, dont know what it threw
  91. return E_UNEXPECTED;
  92. }
  93. }
  94. //-----------------------------------------------------------------------------------------
  95. // Name: get_CurrentPosition(LONGLONG*)
  96. //-----------------------------------------------------------------------------------------
  97. STDMETHOD(get_CurrentPosition)(/*[out,retval]*/long *lPosition) {
  98. HRESULT hr = S_OK;
  99. LONGLONG tempval;
  100. PositionModeList curMode;
  101. try{
  102. // Checking args and init'ing interfaces
  103. if (!lPosition){
  104. return E_POINTER;
  105. }
  106. if (!m_pGraph) {
  107. // graph not valid
  108. return ImplReportError(__uuidof(T), IDS_INVALID_STATE, __uuidof(IMSVidPlayback), HRESULT_FROM_WIN32(ERROR_INVALID_STATE));
  109. }
  110. // See if object supports IMediaSeeking
  111. PQMediaSeeking PQIMSeeking(m_pGraph);
  112. if(PQIMSeeking){
  113. // Find out what postion mode is being used
  114. hr = get_PositionMode(&curMode);
  115. if(FAILED(hr)){
  116. return hr;
  117. }
  118. hr = PQIMSeeking->GetCurrentPosition(&tempval);
  119. if(FAILED(hr)){
  120. return hr;
  121. }
  122. // If it is FrameMode no conversion needed
  123. if(curMode == FrameMode){
  124. *lPosition = static_cast<long>(tempval);
  125. hr = S_OK;
  126. return hr;
  127. }
  128. // If it is TenthsSecondsMode need to be converted from 100 nanosecond units
  129. else if(curMode == TenthsSecondsMode){
  130. *lPosition = static_cast<long>(tempval / nano_to_hundredths);
  131. hr = S_OK;
  132. return hr;
  133. }
  134. // If it is some other mode not supported by the vidctl
  135. else{
  136. return E_UNEXPECTED;
  137. }
  138. }
  139. // See if object supports IMediaPostion
  140. PQMediaPosition PQIMPos(m_pGraph);
  141. if(PQIMPos){
  142. // Get position
  143. double tempDub;
  144. hr = PQIMPos->get_CurrentPosition(&tempDub);
  145. // IMediaPostion only supports 100 Nanosecond units
  146. *lPosition = static_cast<long>(tempDub / nano_to_hundredths);
  147. hr = S_OK;
  148. return hr;
  149. }
  150. // Could Not QI IMedia Seeking or Position
  151. return ImplReportError(__uuidof(T), IDS_E_CANTQI , __uuidof(IMSVidPlayback), E_NOINTERFACE);
  152. }
  153. catch(HRESULT hrTmp){
  154. // Something went bad, threw a HRESULT
  155. return ImplReportError(__uuidof(T), IDS_INVALID_STATE , __uuidof(IMSVidPlayback), hrTmp);
  156. }
  157. catch(...){
  158. // Something went bad, dont know what it threw
  159. return E_UNEXPECTED;
  160. }
  161. }
  162. //-----------------------------------------------------------------------------------------
  163. // Name: put_CurrentPosition(LONGLONG)
  164. //-----------------------------------------------------------------------------------------
  165. STDMETHOD(put_CurrentPosition)(/*[in]*/long lPosition) {
  166. HRESULT hr = S_OK;
  167. LONGLONG tempval = 0;
  168. PositionModeList curMode;
  169. LONG curPos;
  170. try{
  171. // Checking args and interfaces
  172. if (!m_pGraph) {
  173. return ImplReportError(__uuidof(T), IDS_INVALID_STATE, __uuidof(IMSVidPlayback), HRESULT_FROM_WIN32(ERROR_INVALID_STATE));
  174. }
  175. hr = get_CurrentPosition(&curPos);
  176. if(curPos == lPosition){
  177. return NOERROR;
  178. }
  179. // Check for a IMediaSeeking Interface
  180. PQMediaSeeking PQIMSeeking(m_pGraph);
  181. if(PQIMSeeking){
  182. // Get the position Mode
  183. hr = get_PositionMode(&curMode);
  184. if(FAILED(hr)){
  185. return hr;
  186. }
  187. tempval = lPosition;
  188. // If it is in TenthsSecondsMode convert input into 100 nanosecond units
  189. if(curMode == TenthsSecondsMode){
  190. tempval = static_cast<LONGLONG>(lPosition);
  191. tempval = tempval * nano_to_hundredths;
  192. }
  193. // If it is in some other mode
  194. else if(curMode != FrameMode){
  195. return E_UNEXPECTED;
  196. }
  197. // Set the new Position
  198. #if 0
  199. if(curPos > lPosition && !m_pGraph.IsStopped()){
  200. DWORD seekingFlags = AM_SEEKING_CanSeekBackwards;
  201. hr = PQIMSeeking->CheckCapabilities(&seekingFlags);
  202. if(FAILED(hr)){
  203. return hr;
  204. }
  205. }
  206. #endif
  207. hr = PQIMSeeking->SetPositions(&tempval, AM_SEEKING_AbsolutePositioning, NULL, 0);
  208. return hr;
  209. }
  210. // Check for a IMediaPostion
  211. PQMediaPosition PQIMPos(m_pGraph);
  212. if(PQIMPos){
  213. if(curPos > lPosition && !m_pGraph.IsStopped()){
  214. long canSeekBackwardRetVal;
  215. PQIMPos->CanSeekBackward(&canSeekBackwardRetVal);
  216. if(canSeekBackwardRetVal != -1){// OATRUE = -1
  217. return E_INVALIDARG;
  218. }
  219. }
  220. // IMediaPosition only does 100 nanosecond units
  221. double tempDub = lPosition;
  222. tempDub = tempDub * nano_to_hundredths;
  223. hr = PQIMPos->put_CurrentPosition(tempDub);
  224. return hr;
  225. }
  226. // Could Not QI Media Position or Seeking
  227. return ImplReportError(__uuidof(T), IDS_E_CANTQI , __uuidof(IMSVidPlayback), E_NOINTERFACE);
  228. }
  229. catch(HRESULT hrTmp){
  230. // Something went bad, threw a HRESULT
  231. return ImplReportError(__uuidof(T), IDS_INVALID_STATE , __uuidof(IMSVidPlayback), hrTmp);
  232. }
  233. catch(...){
  234. // Something went bad, dont know what it threw
  235. return E_UNEXPECTED;
  236. }
  237. }
  238. //-----------------------------------------------------------------------------------------
  239. // Name: put_PositionMode(LONGLONG)
  240. //-----------------------------------------------------------------------------------------
  241. STDMETHOD(put_PositionMode)(/*[in]*/PositionModeList lPositionMode) {
  242. HRESULT hr = S_OK;
  243. double testval;
  244. get_Rate(&testval);
  245. try{
  246. // Checking args and interfaces
  247. if (!m_pGraph) {
  248. // graph not valid
  249. return ImplReportError(__uuidof(T), IDS_INVALID_STATE, __uuidof(IMSVidPlayback), HRESULT_FROM_WIN32(ERROR_INVALID_STATE));
  250. }
  251. // only valid values
  252. if(lPositionMode != FrameMode && lPositionMode != TenthsSecondsMode){
  253. return E_INVALIDARG;
  254. }
  255. // Try for a IMediaSeeking
  256. PQMediaSeeking PQIMSeeking(m_pGraph);
  257. if(PQIMSeeking){
  258. // Set the new mode
  259. if(lPositionMode == FrameMode){
  260. return PQIMSeeking->SetTimeFormat( &( static_cast<GUID>(TIME_FORMAT_FRAME) ) );
  261. }
  262. if(lPositionMode == TenthsSecondsMode){
  263. return PQIMSeeking->SetTimeFormat(&(static_cast<GUID>(TIME_FORMAT_MEDIA_TIME)));
  264. }
  265. }
  266. // Try for a IMediaPosition
  267. PQMediaPosition PQIMPos(m_pGraph);
  268. if(PQIMPos){
  269. // Only supports TenthsSecondsMode
  270. if(lPositionMode == TenthsSecondsMode){
  271. return S_OK;
  272. }
  273. else{
  274. return E_FAIL;
  275. }
  276. }
  277. // Could Not QI
  278. return ImplReportError(__uuidof(T), IDS_E_CANTQI , __uuidof(IMSVidPlayback), E_NOINTERFACE);
  279. }
  280. catch(HRESULT hrTmp){
  281. // Something went bad, threw a HRESULT
  282. return ImplReportError(__uuidof(T), IDS_INVALID_STATE , __uuidof(IMSVidPlayback), hrTmp);
  283. }
  284. catch(...){
  285. // Something went bad, dont know what it threw
  286. return E_UNEXPECTED;
  287. }
  288. }
  289. //-----------------------------------------------------------------------------------------
  290. // Name: get_PositionMode(LONGLONG*)
  291. //-----------------------------------------------------------------------------------------
  292. STDMETHOD(get_PositionMode)(/*[out,retval]*/PositionModeList* lPositionMode) {
  293. HRESULT hr = S_OK;
  294. double testval;
  295. get_Rate(&testval);
  296. try{
  297. // Checking args and interfaces
  298. if(!lPositionMode){
  299. return E_POINTER;
  300. }
  301. if (!m_pGraph) {
  302. // graph not valid
  303. return ImplReportError(__uuidof(T), IDS_INVALID_STATE, __uuidof(IMSVidPlayback), HRESULT_FROM_WIN32(ERROR_INVALID_STATE));
  304. }
  305. // Get an IMediaSeeking Interface
  306. PQMediaSeeking PQIMSeeking(m_pGraph);
  307. if(PQIMSeeking){
  308. // Get the mode
  309. GUID cur_mode;
  310. hr = PQIMSeeking->GetTimeFormat(&cur_mode);
  311. if(FAILED(hr)){
  312. return hr;
  313. }
  314. // Check to see which mode it is in
  315. if(cur_mode == static_cast<GUID>(TIME_FORMAT_FRAME)){
  316. *lPositionMode = FrameMode;
  317. return S_OK;
  318. }
  319. if(cur_mode == static_cast<GUID>(TIME_FORMAT_MEDIA_TIME)){
  320. *lPositionMode = TenthsSecondsMode;
  321. return S_OK;
  322. }
  323. // Not in a vidctl supported mode
  324. else{
  325. return E_FAIL;
  326. }
  327. }
  328. // Get IMediaPosition
  329. PQMediaPosition PQIMPos(m_pGraph);
  330. if(PQIMPos){
  331. // Only supports TenthsSecondsMode
  332. *lPositionMode = TenthsSecondsMode;
  333. return S_OK;
  334. }
  335. // Could Not QI
  336. return ImplReportError(__uuidof(T), IDS_E_CANTQI , __uuidof(IMSVidPlayback), E_NOINTERFACE);
  337. }
  338. catch(HRESULT hrTmp){
  339. // Something went bad, threw a HRESULT
  340. return ImplReportError(__uuidof(T), IDS_INVALID_STATE , __uuidof(IMSVidPlayback), hrTmp);
  341. }
  342. catch(...){
  343. // Something went bad, dont know what it threw
  344. return E_UNEXPECTED;
  345. }
  346. }
  347. STDMETHOD(get_Duration)(double *dPos) {
  348. return E_NOTIMPL;
  349. }
  350. STDMETHOD(get_PrerollTime)(double *dPos) {
  351. return E_NOTIMPL;
  352. }
  353. STDMETHOD(put_PrerollTime)(double dPos) {
  354. return E_NOTIMPL;
  355. }
  356. STDMETHOD(get_StartTime)(double *StartTime) {
  357. return E_NOTIMPL;
  358. }
  359. STDMETHOD(put_StartTime)(double StartTime) {
  360. return E_NOTIMPL;
  361. }
  362. STDMETHOD(get_StopTime)(double *StopTime) {
  363. return E_NOTIMPL;
  364. }
  365. STDMETHOD(put_StopTime)(double StopTime) {
  366. return E_NOTIMPL;
  367. }
  368. //-----------------------------------------------------------------------------------------
  369. // Name: get_EnableResetOnStop(VARIANT_BOOL*)
  370. //-----------------------------------------------------------------------------------------
  371. STDMETHOD(get_EnableResetOnStop)(/*[out, retval]*/ VARIANT_BOOL *pVal){
  372. HRESULT hr = S_OK;
  373. try {
  374. if(NULL == pVal){
  375. throw(E_POINTER);
  376. }
  377. if(m_fEnableResetOnStop == true){
  378. *pVal = VARIANT_TRUE;
  379. }
  380. else{
  381. *pVal = VARIANT_FALSE;
  382. }
  383. }
  384. catch(HRESULT hrTmp){
  385. hr = hrTmp;
  386. }
  387. catch(...){
  388. hr = E_UNEXPECTED;
  389. }
  390. return hr;
  391. }// end of function get_EnableResetOnStop
  392. //-----------------------------------------------------------------------------------------
  393. // Name: put_EnableResetOnStop(VARIANT_BOOL)
  394. //-----------------------------------------------------------------------------------------
  395. STDMETHOD(put_EnableResetOnStop)(/*[in]*/ VARIANT_BOOL newVal){
  396. HRESULT hr = S_OK;
  397. try {
  398. if(newVal == VARIANT_TRUE){
  399. m_fEnableResetOnStop = true;
  400. }
  401. else{
  402. m_fEnableResetOnStop = false;
  403. }
  404. }
  405. catch(...){
  406. hr = E_UNEXPECTED;
  407. }
  408. return hr;
  409. }// end of function put_EnableResetOnStop
  410. //-----------------------------------------------------------------------------------------
  411. // Name: get_CanStep(VARIANT_BOOL, VARIANT_BOOL*)
  412. //-----------------------------------------------------------------------------------------
  413. STDMETHOD(get_CanStep)(VARIANT_BOOL fBackwards, VARIANT_BOOL *pfCan){
  414. // NOTE: NO ONE supports backwords stepping (why not? who knows)
  415. // so just like everyone else we dont either
  416. try{
  417. // Checking args and interfaces
  418. if(NULL == pfCan){
  419. // Passed a NULL Pointer
  420. return E_POINTER;
  421. }
  422. if (!m_pGraph) {
  423. // graph not valid
  424. return ImplReportError(__uuidof(T), IDS_INVALID_STATE, __uuidof(IMSVidPlayback), HRESULT_FROM_WIN32(ERROR_INVALID_STATE));
  425. }
  426. //Get a VideoFrameStep Interface
  427. PQVideoFrameStep pVFS(m_pGraph);
  428. if(!pVFS){
  429. // Could Not QI
  430. return ImplReportError(__uuidof(T), IDS_E_CANTQI , __uuidof(IMSVidPlayback), E_NOINTERFACE);
  431. }
  432. #if BACKWARDS_STEPPING // Checking for Backward Stepping should always be 0
  433. if(fBackwards == VARIANT_TRUE){
  434. // Backwords Stepping Not Supported Most Likely
  435. if(pVFS->CanStep(TRUE, NULL)==S_OK){
  436. // It is all Good, Can Step Backwords
  437. *pfCan = VARIANT_TRUE;
  438. return S_OK;
  439. }
  440. *pfCan = VARIANT_FALSE;
  441. return S_OK;
  442. }
  443. #else // Still checking for Backward Stepping
  444. if(fBackwards == VARIANT_TRUE){
  445. *pfCan = VARIANT_FALSE;
  446. return S_OK;
  447. }
  448. #endif // End checking for Backward Stepping
  449. // Checking for Forward Stepping
  450. else{
  451. if(pVFS->CanStep(FALSE, NULL)==S_OK){
  452. // It is all Good, Can Step Forward
  453. *pfCan = VARIANT_TRUE;
  454. return S_OK;
  455. }
  456. else{
  457. // Can't Step
  458. *pfCan = VARIANT_FALSE;
  459. return S_OK;
  460. }
  461. }
  462. }
  463. catch(HRESULT hrTmp){
  464. // Something went bad, threw a HRESULT
  465. return ImplReportError(__uuidof(T), IDS_INVALID_STATE , __uuidof(IMSVidPlayback), hrTmp);
  466. }
  467. catch(...){
  468. // Something went bad, dont know what it threw
  469. return E_UNEXPECTED;
  470. }
  471. }
  472. //-----------------------------------------------------------------------------------------
  473. // Name: Step(long)
  474. //-----------------------------------------------------------------------------------------
  475. STDMETHOD(Step)(long lStep){
  476. try{
  477. // Checking args and interfaces
  478. if (!m_pGraph) {
  479. // graph not valid
  480. return ImplReportError(__uuidof(T), IDS_INVALID_STATE, __uuidof(IMSVidPlayback), HRESULT_FROM_WIN32(ERROR_INVALID_STATE));
  481. }
  482. PQVideoFrameStep pVFS(m_pGraph);
  483. if(!pVFS){
  484. // Could Not QI
  485. return ImplReportError(__uuidof(T), IDS_E_CANTQI , __uuidof(IMSVidPlayback), E_NOINTERFACE);
  486. }
  487. #if BACKWARDS_STEPPING // Checking for Backward Stepping should always be 0
  488. // If backwords stepping set rate or what ever needs to be done
  489. if(lStep < 0){
  490. // Backwords Stepping Not Supported Most Likely
  491. if(pVFS->CanStep(TRUE, NULL)==S_OK){
  492. // It is all Good, Can Step Backwords
  493. CComQIPtr<IMediaPosition> IMPos(m_pGraph);
  494. CComQIPtr<IMediaControl> IMCon(m_pGraph);
  495. if(IMPos&&IMCon){
  496. OAFilterState enterState;
  497. IMCon->GetState(INFINITE , &enterState);
  498. HRESULT hr = IMPos->put_Rate(1);
  499. if(SUCCEEDED(hr)){
  500. hr = pVFS->Step((-lStep), NULL);
  501. if(SUCCEEDED(hr)){
  502. return S_OK;
  503. }
  504. else{
  505. return E_UNEXPECTED;
  506. }
  507. }
  508. }
  509. }
  510. // Backwords stepping not supported
  511. return E_NOTIMPL;
  512. }
  513. #else // Still checking for Backward Stepping
  514. if(lStep < 0){
  515. return E_NOTIMPL;
  516. }
  517. #endif // End checking for Backward Stepping
  518. // Make it step
  519. return pVFS->Step(lStep, NULL);
  520. }
  521. catch(HRESULT hrTmp){
  522. // Something went bad, threw a HRESULT
  523. return ImplReportError(__uuidof(T), IDS_INVALID_STATE , __uuidof(IMSVidPlayback), hrTmp);
  524. }
  525. catch(...){
  526. // Something went bad, dont know what it threw
  527. return E_UNEXPECTED;
  528. }
  529. }
  530. // note: the following methods control the playback device *NOT* the graph.
  531. // if the underlying source filter only supports these functions via
  532. // imediacontrol on the graph then this device segment object should return E_NOTIMPL.
  533. STDMETHOD(Run)() {
  534. return E_NOTIMPL;
  535. }
  536. STDMETHOD(Pause)() {
  537. return E_NOTIMPL;
  538. }
  539. STDMETHOD(Stop)() {
  540. return E_NOTIMPL;
  541. }
  542. //-----------------------------------------------------------------------------------------
  543. // Name: put_Rate(double)
  544. //-----------------------------------------------------------------------------------------
  545. STDMETHOD(put_Rate)(double lRate){
  546. HRESULT hr = S_OK;
  547. try{
  548. /*** Checking args and init'ing interfaces ***/
  549. if (!m_pGraph) {
  550. // graph not valid
  551. return ImplReportError(__uuidof(T), IDS_INVALID_STATE, __uuidof(IMSVidPlayback), HRESULT_FROM_WIN32(ERROR_INVALID_STATE));
  552. }
  553. // Attempt to set the rate using IMediaSeeking
  554. PQMediaSeeking PQIMSeeking(m_pGraph);
  555. if(PQIMSeeking){
  556. return PQIMSeeking->SetRate(lRate);
  557. }
  558. // If IMediaSeeking FAILS try IMediaPostion
  559. PQMediaPosition PQIMPos(m_pGraph);
  560. if(PQIMPos){
  561. // Change rate
  562. return PQIMPos->put_Rate((double)lRate);
  563. }
  564. // Could Not QI Either one set the error
  565. return ImplReportError(__uuidof(T), IDS_E_CANTQI , __uuidof(IMSVidPlayback), E_NOINTERFACE);
  566. }
  567. catch(HRESULT hrTmp){
  568. // Something went bad, threw a HRESULT
  569. return ImplReportError(__uuidof(T), IDS_INVALID_STATE , __uuidof(IMSVidPlayback), hrTmp);
  570. }
  571. catch(...){
  572. // Something went bad, dont know what it threw
  573. return E_UNEXPECTED;
  574. }
  575. }
  576. //-----------------------------------------------------------------------------------------
  577. // Name: get_Rate(double*)
  578. //-----------------------------------------------------------------------------------------
  579. STDMETHOD(get_Rate)(double *plRate){
  580. HRESULT hr = S_OK;
  581. double curRate = 1;
  582. try{
  583. /*** Checking args and init'ing interfaces ***/
  584. if (!plRate){
  585. return E_POINTER;
  586. }
  587. if (!m_pGraph) {
  588. // graph not valid
  589. return ImplReportError(__uuidof(T), IDS_INVALID_STATE, __uuidof(IMSVidPlayback), HRESULT_FROM_WIN32(ERROR_INVALID_STATE));
  590. }
  591. PQMediaSeeking PQIMSeeking(m_pGraph);
  592. if(PQIMSeeking){
  593. hr = PQIMSeeking->GetRate(&curRate);
  594. }
  595. else{
  596. PQMediaPosition PQIMPos(m_pGraph);
  597. if(PQIMPos){
  598. // Get rate
  599. hr = PQIMPos->get_Rate(&curRate);
  600. }
  601. // Could Not QI
  602. else{
  603. return ImplReportError(__uuidof(T), IDS_E_CANTQI , __uuidof(IMSVidPlayback), E_NOINTERFACE);
  604. }
  605. }
  606. if(SUCCEEDED(hr)){
  607. *plRate = curRate;
  608. TRACELSM(TRACE_DETAIL, (dbgDump << "Playbackimpl::get_Rate() rate = " << curRate), "");
  609. }
  610. else{
  611. TRACELSM(TRACE_ERROR, (dbgDump << "Playbackimpl::get_Rate() get_rate failed"), "");
  612. }
  613. return hr;
  614. }
  615. catch(HRESULT hrTmp){
  616. // Something went bad, threw a HRESULT
  617. return ImplReportError(__uuidof(T), IDS_INVALID_STATE , __uuidof(IMSVidPlayback), hrTmp);
  618. }
  619. catch(...){
  620. // Something went bad, dont know what it threw
  621. return E_UNEXPECTED;
  622. }
  623. }
  624. };
  625. }; // namespace
  626. #endif
  627. // end of file - playbackimpl.h