home *** CD-ROM | disk | FTP | other *** search
/ The Net: Ultimate Internet Guide / WWLCD1.ISO / mac / SiteBldr / AMOVIE / SDK / _SETUP / COMMON.Z / mfcdoc.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-03-23  |  10.4 KB  |  382 lines

  1. //==========================================================================;
  2. //
  3. //  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4. //  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5. //  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6. //  PURPOSE.
  7. //
  8. //  Copyright (c) 1992 - 1996  Microsoft Corporation.  All Rights Reserved.
  9. //
  10. //--------------------------------------------------------------------------;
  11. //
  12. // playdoc.cpp : implementation of the CPlayerDoc class
  13. //
  14.  
  15. #include "stdafx.h"
  16. #include <reftime.h>
  17. #include "mfcplay.h"
  18.  
  19. #include "mfcdoc.h"
  20.  
  21. #ifdef _DEBUG
  22. #undef THIS_FILE
  23. static char BASED_CODE THIS_FILE[] = __FILE__;
  24. #endif
  25.  
  26. /////////////////////////////////////////////////////////////////////////////
  27. // CPlayerDoc
  28.  
  29. IMPLEMENT_DYNCREATE(CPlayerDoc, CDocument)
  30.  
  31. BEGIN_MESSAGE_MAP(CPlayerDoc, CDocument)
  32.     //{{AFX_MSG_MAP(CPlayerDoc)
  33.     ON_UPDATE_COMMAND_UI(ID_MEDIA_PLAY, OnUpdateMediaPlay)
  34.     ON_UPDATE_COMMAND_UI(ID_MEDIA_PAUSE, OnUpdateMediaPause)
  35.     ON_UPDATE_COMMAND_UI(ID_MEDIA_STOP, OnUpdateMediaStop)
  36.     ON_COMMAND(ID_MEDIA_PLAY, OnMediaPlay)
  37.     ON_COMMAND(ID_MEDIA_PAUSE, OnMediaPause)
  38.     ON_COMMAND(ID_MEDIA_STOP, OnMediaStop)
  39.     //}}AFX_MSG_MAP
  40. END_MESSAGE_MAP()
  41.  
  42. /////////////////////////////////////////////////////////////////////////////
  43. // CPlayerDoc construction/destruction
  44.  
  45. CPlayerDoc::CPlayerDoc()
  46. {
  47.     // TODO: add one-time construction code here
  48.     m_pGraph = NULL;
  49.     m_State = Uninitialized;
  50.     m_hGraphNotifyEvent = NULL;
  51.  
  52.     ((CPlayerApp *) AfxGetApp())->OnDocumentCreated( this );
  53. }
  54.  
  55. BOOL CPlayerDoc::CreateFilterGraph(void) {
  56.     HRESULT hr;    // return code
  57.  
  58.     ASSERT(m_pGraph == NULL);
  59.  
  60.     hr = CoCreateInstance(CLSID_FilterGraph,         // get this documents graph object
  61.                           NULL,
  62.                           CLSCTX_INPROC_SERVER,
  63.                           IID_IGraphBuilder,
  64.                           (void **) &m_pGraph);
  65.     if (FAILED(hr)){
  66.         m_pGraph = NULL;
  67.         return FALSE;
  68.     }
  69.  
  70.     // get hold of the event notification handle so we can wait for
  71.     // completion
  72.     IMediaEvent *pME;
  73.     hr = m_pGraph->QueryInterface(IID_IMediaEvent, (void **) &pME);
  74.     if (FAILED(hr)) {
  75.         DeleteContents();
  76.         return FALSE;
  77.     }
  78.  
  79.     hr = pME->GetEventHandle((OAEVENT*) &m_hGraphNotifyEvent);
  80.  
  81.     pME->Release();
  82.  
  83.     if (FAILED(hr)) {
  84.         DeleteContents();
  85.         return FALSE;
  86.     }
  87.  
  88.     return TRUE;
  89. }
  90.  
  91. void CPlayerDoc::DeleteContents( void ){
  92.  
  93.     if (m_pGraph != NULL) {
  94.         m_pGraph->Release();
  95.         m_pGraph = NULL;
  96.     }
  97.  
  98.  
  99.     // this event is owned by the filtergraph and thus is no longer valid
  100.     m_hGraphNotifyEvent = NULL;
  101.  
  102.     m_State = Uninitialized;
  103. }
  104.  
  105. CPlayerDoc::~CPlayerDoc()
  106. {
  107.     DeleteContents();
  108.  
  109.     ((CPlayerApp *) AfxGetApp())->OnDocumentDestroyed( this );
  110. }
  111.  
  112.  
  113. /////////////////////////////////////////////////////////////////////////////
  114. // CPlayerDoc diagnostics
  115.  
  116. #ifdef _DEBUG
  117. void CPlayerDoc::AssertValid() const
  118. {
  119.     CDocument::AssertValid();
  120. }
  121.  
  122. void CPlayerDoc::Dump(CDumpContext& dc) const
  123. {
  124.     CDocument::Dump(dc);
  125. }
  126. #endif //_DEBUG
  127.  
  128. /////////////////////////////////////////////////////////////////////////////
  129. // CPlayerDoc commands
  130.  
  131. void CPlayerDoc::OnUpdateMediaPlay(CCmdUI* pCmdUI)
  132. {
  133.     pCmdUI->Enable( CanPlay() );
  134.     
  135. }
  136.  
  137. void CPlayerDoc::OnUpdateMediaPause(CCmdUI* pCmdUI)
  138. {
  139.     pCmdUI->Enable( CanPause() );
  140.     
  141. }
  142.  
  143. void CPlayerDoc::OnUpdateMediaStop(CCmdUI* pCmdUI)
  144. {
  145.     pCmdUI->Enable( CanStop() );
  146.     
  147. }
  148.  
  149. void CPlayerDoc::OnMediaPlay()
  150. {
  151.     if( CanPlay() ){
  152.         HRESULT    hr;
  153.         IMediaControl *pMC;
  154.  
  155.         // Obtain the interface to our filter graph
  156.         hr = m_pGraph->QueryInterface(IID_IMediaControl, (void **) &pMC);
  157.  
  158.         if( SUCCEEDED(hr) ){
  159.             // Ask the filter graph to play and release the interface
  160.  
  161.             // default behaviour is to carry on from where we stopped last
  162.             // time.
  163.             //
  164.             // if you want it to do this, but rewind at the end then
  165.             // define REWIND.
  166.             // Otherwise you probably want to always start from the
  167.             // beginning -> define FROM_START (in OnMediaStop)
  168. #undef REWIND
  169. #define FROM_START
  170.  
  171. #ifdef REWIND
  172.             IMediaPosition * pMP;
  173.             hr = m_pGraph->QueryInterface(IID_IMediaPosition, (void**) &pMP);
  174.             if (SUCCEEDED(hr)) {
  175.                 // start from last position, but rewind if near the
  176.                 // end
  177.                 REFTIME tCurrent, tLength;
  178.                 hr = pMP->get_Duration(&tLength);
  179.                 if (SUCCEEDED(hr)) {
  180.                     hr = pMP->get_CurrentPosition(&tCurrent);
  181.                     if (SUCCEEDED(hr)) {
  182.                         // within 1sec of end? (or past end?)
  183.                         if ((tLength - tCurrent) < 1) {
  184.                             pMP->put_CurrentPosition(0);
  185.                         }
  186.                     }
  187.                 }
  188.                 pMP->Release();
  189.             }
  190. #endif
  191.  
  192.  
  193.             hr = pMC->Run();
  194.             pMC->Release();
  195.  
  196.             if( SUCCEEDED(hr) ){
  197.                 m_State=Playing;
  198.                 return;
  199.             }
  200.         }
  201.  
  202.         // Inform the user that an error occurred
  203.         AfxMessageBox(IDS_CANT_PLAY);
  204.  
  205.     }    
  206. }
  207.  
  208. void CPlayerDoc::OnMediaPause()
  209. {
  210.     if( CanPause() ){
  211.         HRESULT    hr;
  212.         IMediaControl *pMC;
  213.  
  214.         // Obtain the interface to our filter graph
  215.         hr = m_pGraph->QueryInterface(IID_IMediaControl, (void **) &pMC);
  216.  
  217.         if( SUCCEEDED(hr) ){
  218.             // Ask the filter graph to pause and release the interface
  219.             hr = pMC->Pause();
  220.             pMC->Release();
  221.  
  222.             if( SUCCEEDED(hr) ){
  223.                 m_State = Paused;
  224.                 return;
  225.             }
  226.         }
  227.  
  228.         // Inform the user that an error occurred
  229.         AfxMessageBox(IDS_CANT_PAUSE);
  230.     }
  231.     
  232. }
  233.  
  234. // stop the graph without rewinding
  235. void CPlayerDoc::OnAbortStop()
  236. {
  237.     if( CanStop() ){
  238.         HRESULT    hr;
  239.         IMediaControl *pMC;
  240.  
  241.         // Obtain the interface to our filter graph
  242.         hr = m_pGraph->QueryInterface(IID_IMediaControl, (void **) &pMC);
  243.  
  244.         if( SUCCEEDED(hr) ){
  245.             // Ask the filter graph to stop and release the interface
  246.             hr = pMC->Stop();
  247. #ifdef FROM_START
  248.             // if we want always to play from the beginning
  249.             // then we should seek back to the start here
  250.             // (on app or user stop request, and also after EC_COMPLETE).
  251.             IMediaPosition * pMP;
  252.             hr = m_pGraph->QueryInterface(IID_IMediaPosition, (void**) &pMP);
  253.             if (SUCCEEDED(hr)) {
  254.                 pMP->put_CurrentPosition(0);
  255.                 pMP->Release();
  256.             }
  257.  
  258.             // no visible rewind or we will re-show the window!
  259.  
  260. #endif
  261.  
  262.             pMC->Release();
  263.  
  264.             if( SUCCEEDED(hr) ){
  265.                 m_State = Stopped;
  266.                 return;
  267.             }
  268.         }
  269.  
  270.         // Inform the user that an error occurred
  271.         AfxMessageBox(IDS_CANT_STOP);
  272.     }
  273. }
  274.  
  275. // There are two different ways to stop a graph. We can stop and then when we
  276. // are later paused or run continue from the same position. Alternatively the
  277. // graph can be set back to the start of the media when it is stopped to have
  278. // a more CDPLAYER style interface. These are both offered here conditionally
  279. // compiled using the FROM_START definition. The main difference is that in
  280. // the latter case we put the current position to zero while we change states
  281.  
  282. void CPlayerDoc::OnMediaStop()
  283. {
  284.     if( CanStop() ){
  285.         HRESULT    hr;
  286.         IMediaControl *pMC;
  287.  
  288.         // Obtain the interface to our filter graph
  289.         hr = m_pGraph->QueryInterface(IID_IMediaControl, (void **) &pMC);
  290.         if( SUCCEEDED(hr) ){
  291.  
  292. #ifdef FROM_START
  293.             IMediaPosition * pMP;
  294.             OAFilterState state;
  295.  
  296.             // Ask the filter graph to pause
  297.             hr = pMC->Pause();
  298.  
  299.             // if we want always to play from the beginning
  300.             // then we should seek back to the start here
  301.             // (on app or user stop request, and also after EC_COMPLETE).
  302.             hr = m_pGraph->QueryInterface(IID_IMediaPosition,
  303.                                           (void**) &pMP);
  304.             if (SUCCEEDED(hr)) {
  305.                 pMP->put_CurrentPosition(0);
  306.                 pMP->Release();
  307.             }
  308.  
  309.             // wait for pause to complete
  310.             pMC->GetState(INFINITE, &state);
  311. #endif
  312.             // now really do the stop
  313.             pMC->Stop();
  314.             pMC->Release();
  315.             m_State = Stopped;
  316.             return;
  317.         }
  318.         // Inform the user that an error occurred
  319.         AfxMessageBox(IDS_CANT_STOP);
  320.     }
  321. }
  322.  
  323.  
  324. BOOL CPlayerDoc::OnOpenDocument(LPCTSTR lpszPathName)
  325. {
  326.     WCHAR    wPath[MAX_PATH];
  327.  
  328.     DeleteContents();
  329.  
  330.     if ( !CreateFilterGraph() ) {
  331.         AfxMessageBox(IDS_CANT_INIT_QUARTZ);
  332.         return FALSE;
  333.     }
  334.  
  335.     MultiByteToWideChar( CP_ACP, 0, lpszPathName,
  336.                          -1, wPath, MAX_PATH );
  337.  
  338.  
  339.     if (FAILED( m_pGraph->RenderFile(wPath, NULL) )) {
  340.         AfxMessageBox(IDS_CANT_RENDER_FILE);
  341.         return FALSE;
  342.     }
  343.  
  344.     m_State = Stopped;
  345.  
  346.     return TRUE;
  347. }
  348.  
  349. //
  350. // If the event handle is valid, ask the graph
  351. // if anything has happened. eg the graph has stopped...
  352. void CPlayerDoc::OnGraphNotify(void) {
  353.     IMediaEvent *pME;
  354.     long lEventCode, lParam1, lParam2;
  355.  
  356.     ASSERT( m_hGraphNotifyEvent != NULL );
  357.  
  358.     if( SUCCEEDED(m_pGraph->QueryInterface(IID_IMediaEvent, (void **) &pME))) {
  359.         if( SUCCEEDED(pME->GetEvent(&lEventCode, &lParam1, &lParam2, 0))) {
  360.  
  361.             // if this is a normal stop, then we do a rewind as
  362.             // we would if the user pressed stop. For an abort,
  363.             // we don't touch this.
  364.             if (lEventCode == EC_COMPLETE) {
  365.                 OnMediaStop();
  366.             } else if ((lEventCode == EC_ERRORABORT) ||
  367.                        (lEventCode == EC_USERABORT)) {
  368.  
  369.                 // put the graph into stop mode but don't mess with it.
  370.                 OnAbortStop();
  371.             }
  372.         }
  373.         pME->Release();
  374.     }
  375.  
  376.     // The toolbar will only be updated after a message has been received,
  377.     // so send a dummy message
  378.     PostMessage( AfxGetMainWnd()->m_hWnd, WM_WAKEUP, 0, 0 );
  379.  
  380. }
  381.  
  382.