home *** CD-ROM | disk | FTP | other *** search
- //==========================================================================;
- //
- // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
- // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
- // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
- // PURPOSE.
- //
- // Copyright (c) 1992 - 1996 Microsoft Corporation. All Rights Reserved.
- //
- //--------------------------------------------------------------------------;
- //
- // playdoc.cpp : implementation of the CPlayerDoc class
- //
-
- #include "stdafx.h"
- #include <reftime.h>
- #include "mfcplay.h"
-
- #include "mfcdoc.h"
-
- #ifdef _DEBUG
- #undef THIS_FILE
- static char BASED_CODE THIS_FILE[] = __FILE__;
- #endif
-
- /////////////////////////////////////////////////////////////////////////////
- // CPlayerDoc
-
- IMPLEMENT_DYNCREATE(CPlayerDoc, CDocument)
-
- BEGIN_MESSAGE_MAP(CPlayerDoc, CDocument)
- //{{AFX_MSG_MAP(CPlayerDoc)
- ON_UPDATE_COMMAND_UI(ID_MEDIA_PLAY, OnUpdateMediaPlay)
- ON_UPDATE_COMMAND_UI(ID_MEDIA_PAUSE, OnUpdateMediaPause)
- ON_UPDATE_COMMAND_UI(ID_MEDIA_STOP, OnUpdateMediaStop)
- ON_COMMAND(ID_MEDIA_PLAY, OnMediaPlay)
- ON_COMMAND(ID_MEDIA_PAUSE, OnMediaPause)
- ON_COMMAND(ID_MEDIA_STOP, OnMediaStop)
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
-
- /////////////////////////////////////////////////////////////////////////////
- // CPlayerDoc construction/destruction
-
- CPlayerDoc::CPlayerDoc()
- {
- // TODO: add one-time construction code here
- m_pGraph = NULL;
- m_State = Uninitialized;
- m_hGraphNotifyEvent = NULL;
-
- ((CPlayerApp *) AfxGetApp())->OnDocumentCreated( this );
- }
-
- BOOL CPlayerDoc::CreateFilterGraph(void) {
- HRESULT hr; // return code
-
- ASSERT(m_pGraph == NULL);
-
- hr = CoCreateInstance(CLSID_FilterGraph, // get this documents graph object
- NULL,
- CLSCTX_INPROC_SERVER,
- IID_IGraphBuilder,
- (void **) &m_pGraph);
- if (FAILED(hr)){
- m_pGraph = NULL;
- return FALSE;
- }
-
- // get hold of the event notification handle so we can wait for
- // completion
- IMediaEvent *pME;
- hr = m_pGraph->QueryInterface(IID_IMediaEvent, (void **) &pME);
- if (FAILED(hr)) {
- DeleteContents();
- return FALSE;
- }
-
- hr = pME->GetEventHandle((OAEVENT*) &m_hGraphNotifyEvent);
-
- pME->Release();
-
- if (FAILED(hr)) {
- DeleteContents();
- return FALSE;
- }
-
- return TRUE;
- }
-
- void CPlayerDoc::DeleteContents( void ){
-
- if (m_pGraph != NULL) {
- m_pGraph->Release();
- m_pGraph = NULL;
- }
-
-
- // this event is owned by the filtergraph and thus is no longer valid
- m_hGraphNotifyEvent = NULL;
-
- m_State = Uninitialized;
- }
-
- CPlayerDoc::~CPlayerDoc()
- {
- DeleteContents();
-
- ((CPlayerApp *) AfxGetApp())->OnDocumentDestroyed( this );
- }
-
-
- /////////////////////////////////////////////////////////////////////////////
- // CPlayerDoc diagnostics
-
- #ifdef _DEBUG
- void CPlayerDoc::AssertValid() const
- {
- CDocument::AssertValid();
- }
-
- void CPlayerDoc::Dump(CDumpContext& dc) const
- {
- CDocument::Dump(dc);
- }
- #endif //_DEBUG
-
- /////////////////////////////////////////////////////////////////////////////
- // CPlayerDoc commands
-
- void CPlayerDoc::OnUpdateMediaPlay(CCmdUI* pCmdUI)
- {
- pCmdUI->Enable( CanPlay() );
-
- }
-
- void CPlayerDoc::OnUpdateMediaPause(CCmdUI* pCmdUI)
- {
- pCmdUI->Enable( CanPause() );
-
- }
-
- void CPlayerDoc::OnUpdateMediaStop(CCmdUI* pCmdUI)
- {
- pCmdUI->Enable( CanStop() );
-
- }
-
- void CPlayerDoc::OnMediaPlay()
- {
- if( CanPlay() ){
- HRESULT hr;
- IMediaControl *pMC;
-
- // Obtain the interface to our filter graph
- hr = m_pGraph->QueryInterface(IID_IMediaControl, (void **) &pMC);
-
- if( SUCCEEDED(hr) ){
- // Ask the filter graph to play and release the interface
-
- // default behaviour is to carry on from where we stopped last
- // time.
- //
- // if you want it to do this, but rewind at the end then
- // define REWIND.
- // Otherwise you probably want to always start from the
- // beginning -> define FROM_START (in OnMediaStop)
- #undef REWIND
- #define FROM_START
-
- #ifdef REWIND
- IMediaPosition * pMP;
- hr = m_pGraph->QueryInterface(IID_IMediaPosition, (void**) &pMP);
- if (SUCCEEDED(hr)) {
- // start from last position, but rewind if near the
- // end
- REFTIME tCurrent, tLength;
- hr = pMP->get_Duration(&tLength);
- if (SUCCEEDED(hr)) {
- hr = pMP->get_CurrentPosition(&tCurrent);
- if (SUCCEEDED(hr)) {
- // within 1sec of end? (or past end?)
- if ((tLength - tCurrent) < 1) {
- pMP->put_CurrentPosition(0);
- }
- }
- }
- pMP->Release();
- }
- #endif
-
-
- hr = pMC->Run();
- pMC->Release();
-
- if( SUCCEEDED(hr) ){
- m_State=Playing;
- return;
- }
- }
-
- // Inform the user that an error occurred
- AfxMessageBox(IDS_CANT_PLAY);
-
- }
- }
-
- void CPlayerDoc::OnMediaPause()
- {
- if( CanPause() ){
- HRESULT hr;
- IMediaControl *pMC;
-
- // Obtain the interface to our filter graph
- hr = m_pGraph->QueryInterface(IID_IMediaControl, (void **) &pMC);
-
- if( SUCCEEDED(hr) ){
- // Ask the filter graph to pause and release the interface
- hr = pMC->Pause();
- pMC->Release();
-
- if( SUCCEEDED(hr) ){
- m_State = Paused;
- return;
- }
- }
-
- // Inform the user that an error occurred
- AfxMessageBox(IDS_CANT_PAUSE);
- }
-
- }
-
- // stop the graph without rewinding
- void CPlayerDoc::OnAbortStop()
- {
- if( CanStop() ){
- HRESULT hr;
- IMediaControl *pMC;
-
- // Obtain the interface to our filter graph
- hr = m_pGraph->QueryInterface(IID_IMediaControl, (void **) &pMC);
-
- if( SUCCEEDED(hr) ){
- // Ask the filter graph to stop and release the interface
- hr = pMC->Stop();
- #ifdef FROM_START
- // if we want always to play from the beginning
- // then we should seek back to the start here
- // (on app or user stop request, and also after EC_COMPLETE).
- IMediaPosition * pMP;
- hr = m_pGraph->QueryInterface(IID_IMediaPosition, (void**) &pMP);
- if (SUCCEEDED(hr)) {
- pMP->put_CurrentPosition(0);
- pMP->Release();
- }
-
- // no visible rewind or we will re-show the window!
-
- #endif
-
- pMC->Release();
-
- if( SUCCEEDED(hr) ){
- m_State = Stopped;
- return;
- }
- }
-
- // Inform the user that an error occurred
- AfxMessageBox(IDS_CANT_STOP);
- }
- }
-
- // There are two different ways to stop a graph. We can stop and then when we
- // are later paused or run continue from the same position. Alternatively the
- // graph can be set back to the start of the media when it is stopped to have
- // a more CDPLAYER style interface. These are both offered here conditionally
- // compiled using the FROM_START definition. The main difference is that in
- // the latter case we put the current position to zero while we change states
-
- void CPlayerDoc::OnMediaStop()
- {
- if( CanStop() ){
- HRESULT hr;
- IMediaControl *pMC;
-
- // Obtain the interface to our filter graph
- hr = m_pGraph->QueryInterface(IID_IMediaControl, (void **) &pMC);
- if( SUCCEEDED(hr) ){
-
- #ifdef FROM_START
- IMediaPosition * pMP;
- OAFilterState state;
-
- // Ask the filter graph to pause
- hr = pMC->Pause();
-
- // if we want always to play from the beginning
- // then we should seek back to the start here
- // (on app or user stop request, and also after EC_COMPLETE).
- hr = m_pGraph->QueryInterface(IID_IMediaPosition,
- (void**) &pMP);
- if (SUCCEEDED(hr)) {
- pMP->put_CurrentPosition(0);
- pMP->Release();
- }
-
- // wait for pause to complete
- pMC->GetState(INFINITE, &state);
- #endif
- // now really do the stop
- pMC->Stop();
- pMC->Release();
- m_State = Stopped;
- return;
- }
- // Inform the user that an error occurred
- AfxMessageBox(IDS_CANT_STOP);
- }
- }
-
-
- BOOL CPlayerDoc::OnOpenDocument(LPCTSTR lpszPathName)
- {
- WCHAR wPath[MAX_PATH];
-
- DeleteContents();
-
- if ( !CreateFilterGraph() ) {
- AfxMessageBox(IDS_CANT_INIT_QUARTZ);
- return FALSE;
- }
-
- MultiByteToWideChar( CP_ACP, 0, lpszPathName,
- -1, wPath, MAX_PATH );
-
-
- if (FAILED( m_pGraph->RenderFile(wPath, NULL) )) {
- AfxMessageBox(IDS_CANT_RENDER_FILE);
- return FALSE;
- }
-
- m_State = Stopped;
-
- return TRUE;
- }
-
- //
- // If the event handle is valid, ask the graph
- // if anything has happened. eg the graph has stopped...
- void CPlayerDoc::OnGraphNotify(void) {
- IMediaEvent *pME;
- long lEventCode, lParam1, lParam2;
-
- ASSERT( m_hGraphNotifyEvent != NULL );
-
- if( SUCCEEDED(m_pGraph->QueryInterface(IID_IMediaEvent, (void **) &pME))) {
- if( SUCCEEDED(pME->GetEvent(&lEventCode, &lParam1, &lParam2, 0))) {
-
- // if this is a normal stop, then we do a rewind as
- // we would if the user pressed stop. For an abort,
- // we don't touch this.
- if (lEventCode == EC_COMPLETE) {
- OnMediaStop();
- } else if ((lEventCode == EC_ERRORABORT) ||
- (lEventCode == EC_USERABORT)) {
-
- // put the graph into stop mode but don't mess with it.
- OnAbortStop();
- }
- }
- pME->Release();
- }
-
- // The toolbar will only be updated after a message has been received,
- // so send a dummy message
- PostMessage( AfxGetMainWnd()->m_hWnd, WM_WAKEUP, 0, 0 );
-
- }
-