CPLAY.C

//==========================================================================; 
//
// 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 - 1997 Microsoft Corporation. All Rights Reserved.
//
//--------------------------------------------------------------------------;

#include "stdwin.h"
#include "cplay.h"
#include "about.h"
#include "file.h"
#include "media.h"
#include "toolbar.h"
#include "resource.h"

//
//
// What this sample illustrates
//
// A simple ActiveMovie application written in C.
//
//
// Summary
//
// This is an ActiveMovie application that is written in C. We create a window
// that has a simple menu allowing files to be opened and closed. The window
// also has three buttons for stopping, pausing and running the media. We are
// written to call the standard filtergraph interfaces. The only complication
// we have added is two UI alternatives. The filter can either be compiled to
// rewind to the start of the media when it is stopped, or alternatively it
// can leave the current position (and therefore frame) wherever it is stopped
//
// Files
//
// about.c Run of the mill about box
// about.h Header file for about box
// assert.c Display a message box
// cplay.c Main application code
// cplay.h And its function protoypes
// file.c Looks after file open dialogs
// file.h And its two function prototypes
// makefile How we build it
// media.c Functions that call the graph
// media.h And their prototypes
// player.rc Visual C++ resource file
// resource.h Header file for resources
// stdwin.c Precompiled header file
// stdwin.h Precompiled header file
// toolbar.c Looks after the app toolbar
// toolbar.h Public function prototypes
//
//


#define UNTITLED_STRING " - Untitled"
#define nMaxResourceStrSize 128

AppVars appVars;


//
// PlayerMessageBox
//
// Load and display an error message
//
void PlayerMessageBox( UINT nResource )
{
char szStr[ nMaxResourceStrSize ];

LoadString( appVars.hInstance, nResource, szStr, nMaxResourceStrSize );
MessageBox( appVars.hwndMainFrame, szStr, appVars.szAppName,
MB_APPLMODAL | MB_OK | MB_ICONEXCLAMATION );

} // PlayerMessageBox


//
// ProcessCommand
//
// Process a WM_COMMAND message to the main window
//
long ProcessCommand( HWND hwnd, UINT wParam, LONG lParam )
{
switch( wParam ){
case ID_FILE_EXIT:
PostQuitMessage( 0 );
break;

case ID_HELP_ABOUT:
DoAboutDialog( appVars.hInstance,hwnd );
break;

case ID_FILE_OPEN:
OpenMediaFile( hwnd, NULL );
break;

case ID_MEDIA_PLAY:
OnMediaPlay( );
break;

case ID_MEDIA_PAUSE:
OnMediaPause( );
break;

case ID_MEDIA_STOP:
OnMediaStop( );
break;

default:
return DefWindowProc( hwnd, WM_COMMAND, wParam, lParam );
}
return (LRESULT) 0;

} // ProcessCommand


//
// OnGetMinMaxInfo
//
// Sets the minimum size of the main window and the maximum height
//
void OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)
{
RECT rectRequired;
SIZE sizeToolbar;

// Our client area is going to be the toolbar, so find our its size
CalcRequiredSize( &sizeToolbar );

rectRequired.left = rectRequired.top = 0;
rectRequired.right = sizeToolbar.cx;
rectRequired.bottom = sizeToolbar.cy;

// Take into account the menu, caption and thick frame
AdjustWindowRect( &rectRequired, WS_CAPTION|WS_THICKFRAME, TRUE );

// Set the min/max sizes
lpMMI->ptMinTrackSize.x = rectRequired.right - rectRequired.left;
lpMMI->ptMinTrackSize.y = lpMMI->ptMaxTrackSize.y =
rectRequired.bottom - rectRequired.top;

} // OnGetMinMaxInfo


//
// MainFrameProc
//
// Handles the message sent to the main window
//
long FAR PASCAL MainFrameProc( HWND hwnd, UINT message, UINT wParam, LONG lParam)
{
switch( message ){
case WM_DESTROY:
PostQuitMessage( 0 );
break;

case WM_GETMINMAXINFO:
OnGetMinMaxInfo( (MINMAXINFO FAR *) lParam );
break;

case WM_DRAWITEM:
DrawButton( appVars.hInstance, (DRAWITEMSTRUCT FAR *) lParam );
break;

case WM_INITMENUPOPUP:
if( lParam == 1 ){ // Media popup menu
EnableMenuItem( (HMENU) wParam, ID_MEDIA_PLAY, CanPlay() ? MF_ENABLED : MF_GRAYED );
EnableMenuItem( (HMENU) wParam, ID_MEDIA_PAUSE, CanPause() ? MF_ENABLED : MF_GRAYED );
EnableMenuItem( (HMENU) wParam, ID_MEDIA_STOP, CanStop() ? MF_ENABLED : MF_GRAYED );
} else
return DefWindowProc( hwnd, message, wParam, lParam );
break;

case WM_COMMAND:
return ProcessCommand( hwnd, wParam, lParam );

default:
return DefWindowProc( hwnd, message, wParam, lParam );
}
return (LRESULT) 0;

} // MainFrameProc


//
// InitApplication
//
BOOL InitApplication()
{
strcpy( appVars.szAppName, APP_NAME );

// Filter interface initialize?
if( SUCCEEDED( CoInitialize( NULL )))
return TRUE;

return FALSE;
}


//
// UnInitApplication
//
void UnInitApplication()
{
CoUninitialize( );
}


//
// InitInstance
//
// Set the specific instance data and register our main
// window class if it has not been registered already
//
BOOL InitInstance( HANDLE hInstance, HANDLE hPrevInstance )
{
appVars.hInstance = hInstance;

if(!hPrevInstance){
WNDCLASS wndClass;

wndClass.style = CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = MainFrameProc;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = appVars.hInstance;
wndClass.hIcon = LoadIcon( appVars.hInstance, MAKEINTRESOURCE( IDR_MAINFRAME ));
wndClass.hCursor = LoadCursor( NULL, IDC_ARROW );
wndClass.hbrBackground = GetStockObject( LTGRAY_BRUSH );
wndClass.lpszMenuName = MAKEINTRESOURCE( IDR_MAINFRAME );
wndClass.lpszClassName = appVars.szAppName;

RegisterClass( &wndClass );
}

return TRUE;

} // InitInstance


//
// InitMainFrame
//
// Create our main window
//
BOOL InitMainFrame( int nCmdShow )
{
const DWORD Styles = WS_OVERLAPPEDWINDOW &~ WS_MAXIMIZEBOX;
char szTitle[ 30 ];

strcpy( szTitle, APP_NAME );
strcat( szTitle, UNTITLED_STRING );

appVars.hwndMainFrame =
CreateWindow( appVars.szAppName, // Our class name
szTitle, // Window title
Styles, // It's styles
CW_USEDEFAULT, // No x position
CW_USEDEFAULT, // And no y either
0, 65, // Initial sizes
NULL, // No parent window
NULL, // And no menu
appVars.hInstance, // App instance
NULL); // Creation data

ShowWindow( appVars.hwndMainFrame, nCmdShow );
UpdateWindow( appVars.hwndMainFrame );
return TRUE;

} // InitMainFrame


//
// DoMainLoop
//
// Main message loop
//
UINT DoMainLoop()
{
MSG msg;
HANDLE ahObjects[1]; // Handles that need to be waited on
const int cObjects = 1; // Number of objects that we have

// Message loop lasts until we get a WM_QUIT message
// Upon which we shall return from the function

while (TRUE) {
if( (ahObjects[ 0 ] = GetGraphEventHandle()) == NULL ) {
WaitMessage();
} else {

// Wait for any message or a graph notification

DWORD Result = MsgWaitForMultipleObjects( cObjects,
ahObjects,
FALSE,
INFINITE,
QS_ALLINPUT);

// Have we received an event notification

if( Result != (WAIT_OBJECT_0 + cObjects) )
{
if( Result == WAIT_OBJECT_0 ) {
OnGraphNotify();
}
continue;
}
}

// Read all of the messages in this next loop
// removing each message as we read it

while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
return msg.wParam;

TranslateMessage(&msg);
DispatchMessage(&msg);
}
}

} // DoMainLoop


//
// WinMain
//
// Application entry point
//
int PASCAL WinMain( HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpszCmdParam,
int nCmdShow )
{
UINT nReturn;

// Initialise COM and the application
if ( InitApplication() == FALSE ) return 0;

if( InitInstance( hInstance, hPrevInstance ) &&
InitMainFrame( nCmdShow ) &&
InitToolbar( hInstance, appVars.hwndMainFrame ) &&
InitMedia( ) &&
InitFileOpenDialog( appVars.hwndMainFrame ))
{
if( lpszCmdParam[0] != '\0' ) {
OpenMediaFile( appVars.hwndMainFrame, lpszCmdParam );
}

nReturn = DoMainLoop();

// Stop the graph if we can
if( CanStop() )
OnMediaStop();

// Release the filter graph
DeleteContents();
}

UnInitApplication();
return nReturn;

} // WinMain