#include "stdafx.h"
#include <mmsystem.h>
#include <digitalv.h>

#include "cmovie.h"

////////////////////////////////////////////////////////////////////////////
CMovie::CMovie() : CStatic()
{
     m_bMovieOpen = FALSE;
	m_bPlaying   = FALSE;
     m_hWndMovie  = NULL;

	initAVI();
}

////////////////////////////////////////////////////////////////////////////
CMovie::~CMovie()
{
	termAVI();
}

////////////////////////////////////////////////////////////////////////////
BOOL CMovie::Create( LPCTSTR lpszText, DWORD dwStyle, const RECT& rect,
                     CWnd* pParentWnd, UINT nID )
{
     return CStatic::Create( lpszText, dwStyle, rect, pParentWnd, nID );
}

////////////////////////////////////////////////////////////////////////////
BOOL CMovie::Open( LPCTSTR lpszfile )
{
	MCI_DGV_OPEN_PARMS	  mciOpen;
	MCI_DGV_WINDOW_PARMS  mciWindow;
	MCI_DGV_STATUS_PARMS  mciStatus;
	DWORD                 dwError;

	/* we got a filename, now close any old movie and open */
	/* the new one.					*/
	if ( m_bMovieOpen )
		fileCloseMovie();

	/* we have a .AVI movie to open, use MCI */
	/* set up the open parameters */
	mciOpen.dwCallback = 0L;
	mciOpen.wDeviceID  = 0;
	mciOpen.lpstrDeviceType  = NULL;
	mciOpen.lpstrElementName = (LPTSTR)lpszfile;
	mciOpen.lpstrAlias = NULL;
	mciOpen.dwStyle    = WS_CHILD;
	mciOpen.hWndParent = m_hWnd;

	/* try to open the file */
	if ( (dwError = mciSendCommand(0, MCI_OPEN,
		(DWORD)(MCI_OPEN_ELEMENT|MCI_DGV_OPEN_PARENT|MCI_DGV_OPEN_WS),
		(DWORD)(LPMCI_DGV_OPEN_PARMS)&mciOpen)) == 0 )
	{
		/* we opened the file o.k., now set up to play it. */
		m_MCIDeviceID = mciOpen.wDeviceID;	/* save ID */
		m_bMovieOpen  = TRUE;	  /* a movie was opened */

		/* show the playback window */
		mciWindow.dwCallback = 0L;
		mciWindow.hWnd = NULL;
		mciWindow.nCmdShow = SW_SHOW;
		mciWindow.lpstrText = (LPSTR)NULL;
		mciSendCommand( m_MCIDeviceID, MCI_WINDOW,
         				 MCI_DGV_WINDOW_STATE,
                        	 (DWORD)(LPMCI_DGV_WINDOW_PARMS)&mciWindow);

		/* get the window handle */
		mciStatus.dwItem = MCI_DGV_STATUS_HWND;
		mciSendCommand( m_MCIDeviceID, MCI_STATUS, MCI_STATUS_ITEM,
			(DWORD)(LPMCI_STATUS_PARMS)&mciStatus );
		m_hWndMovie = (HWND)mciStatus.dwReturn;

		/* now get the movie centered */
		positionMovie();
	}
	else
	{
		mciGetErrorString( dwError, m_szError, 256 );
		/* generic error for open */
		MessageBox( m_szError, "Error", MB_OK );
		m_bMovieOpen = FALSE;
	}

	/* cause an update to occur */
	InvalidateRect(NULL, FALSE);
	UpdateWindow();

	return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
BOOL CMovie::Play(void)
{
	playMovie(0);
	return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
BOOL CMovie::Stop(void)
{
     fileCloseMovie();
	return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
BOOL CMovie::Close(void)
{
     fileCloseMovie();
	return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
BOOL CMovie::Pause(void)
{
     pauseMovie();
     return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
void CMovie::PositionMovie(void)
{
	positionMovie();
}

/////////////////////////////////////////////////////////////////////////////
BOOL CMovie::Rewind(void)
{
	seekMovie( MOVE_TO_START );
	return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
// seekMovie - seek in the movie depending on the wAction.
//      Possible actions are IDM_HOME (start of movie) or IDM_END (end of movie)
//      Always stop the play before seeking.
/////////////////////////////////////////////////////////////////////////////
void CMovie::seekMovie( int nAction )
{
	/* first stop the movie from playing if it is playing */
	if ( m_bPlaying )
          return;

	if ( nAction == MOVE_TO_START )
	{
		/* home the movie */
		mciSendCommand( m_MCIDeviceID, MCI_SEEK, MCI_SEEK_TO_START,
			(DWORD)(LPVOID)NULL);

	}
	else if ( nAction == MOVE_TO_END )
	{
		/* go to the end of the movie */
		mciSendCommand( m_MCIDeviceID, MCI_SEEK, MCI_SEEK_TO_END,
			(DWORD)(LPVOID)NULL);
	}
}

/////////////////////////////////////////////////////////////////////////////
// initAVI - initialize avi libraries
/////////////////////////////////////////////////////////////////////////////
BOOL CMovie::initAVI(void)
{
	MCI_DGV_OPEN_PARMS	mciOpen;

	/* set up the open parameters */
	mciOpen.dwCallback 		= 0L;
	mciOpen.wDeviceID 		= 0;
	mciOpen.lpstrDeviceType 	= AVI_VIDEO;
	mciOpen.lpstrElementName = NULL;
	mciOpen.lpstrAlias 		= NULL;
	mciOpen.dwStyle 		= 0;
	mciOpen.hWndParent 		= NULL;

	/* try to open the driver */
	return (mciSendCommand(0, MCI_OPEN, (DWORD)(MCI_OPEN_TYPE),
                          (DWORD)(LPMCI_DGV_OPEN_PARMS)&mciOpen) == 0);
}

/////////////////////////////////////////////////////////////////////////////
// termAVI - Closes the opened AVI file and the opened device type.
/////////////////////////////////////////////////////////////////////////////
void CMovie::termAVI(void)
{
	MCIDEVICEID        mciID;
	MCI_GENERIC_PARMS  mciClose;
	//
	// Get the device ID for the opened device type and then close
	// the device type.
	mciID = mciGetDeviceID(AVI_VIDEO);
	mciSendCommand( mciID, MCI_CLOSE, 0L,
                     (DWORD)(LPMCI_GENERIC_PARMS)&mciClose);
}

/////////////////////////////////////////////////////////////////////////////
// fileCloseMovie - close the movie and anything associated	with it.					|
// This function clears the <gfPlaying> and <gfMovieOpen> flags
/////////////////////////////////////////////////////////////////////////////
void CMovie::fileCloseMovie()
{
	MCI_GENERIC_PARMS  mciGeneric;

	mciSendCommand( m_MCIDeviceID, MCI_CLOSE, 0L,
                 	 (DWORD)(LPMCI_GENERIC_PARMS)&mciGeneric);

	m_bPlaying = FALSE;	// can't be playing any longer
	m_bMovieOpen = FALSE;	// no more movies open

	/* cause a total repaint to occur */
	InvalidateRect(NULL, TRUE);
	UpdateWindow();
}

/////////////////////////////////////////////////////////////////////////////
// positionMovie - sets the movie rectange <rcMovie> to be
//		centered within the app's window.
/////////////////////////////////////////////////////////////////////////////
VOID CMovie::positionMovie()
{
	RECT rcMovie;	/* the rect where the movie is positioned      */
				/* for QT/W this is the movie rect, for AVI    */
				/* this is the location of the playback window */
	RECT	rcClient, rcMovieBounds;
	MCI_DGV_RECT_PARMS	mciRect;

	/* if there is no movie yet then just get out of here */
	if ( !m_bMovieOpen )
		return;

	GetClientRect(&rcClient);	/* get the parent windows rect */

	/* get the original size of the movie */
	mciSendCommand( m_MCIDeviceID, MCI_WHERE,
                     (DWORD)(MCI_DGV_WHERE_SOURCE),
                     (DWORD)(LPMCI_DGV_RECT_PARMS)&mciRect);

	CopyRect( &rcMovieBounds, &mciRect.rc );	/* get it in the movie bounds rect */

	rcMovie.left = (rcClient.right/2) - (rcMovieBounds.right / 2);
	rcMovie.top = (rcClient.bottom/2) - (rcMovieBounds.bottom / 2);
	rcMovie.right = rcMovie.left + rcMovieBounds.right;
	rcMovie.bottom = rcMovie.top + rcMovieBounds.bottom;

	/* reposition the playback (child) window */
	::MoveWindow( m_hWndMovie, rcMovie.left, rcMovie.top,
	     	    rcMovieBounds.right, rcMovieBounds.bottom, TRUE );
}

/////////////////////////////////////////////////////////////////////////////
// playMovie - play/pause the movie depending on the state
//	of the <gfPlaying> flag.
// This function sets the <gfPlaying> flag appropriately when done
/////////////////////////////////////////////////////////////////////////////
// OK
void CMovie::playMovie( int nDirection )
{
	// play AVI movie
	DWORD			dwFlags;
	MCI_DGV_PLAY_PARMS	mciPlay;

	// init to play all
	mciPlay.dwCallback = MAKELONG(m_hWnd,0);
	mciPlay.dwFrom = mciPlay.dwTo = 0;
	dwFlags = MCI_NOTIFY;

	mciSendCommand( m_MCIDeviceID, MCI_PLAY, dwFlags,
	                (DWORD)(LPMCI_DGV_PLAY_PARMS)&mciPlay );
}

/////////////////////////////////////////////////////////////////////////////
// OK
void CMovie::pauseMovie(void)
{
	MCI_DGV_PAUSE_PARMS	mciPause;

	// tell it to pause
	mciSendCommand(m_MCIDeviceID, MCI_PAUSE, 0L,
                    (DWORD)(LPMCI_DGV_PAUSE_PARMS)&mciPause);
}

