home *** CD-ROM | disk | FTP | other *** search
- //------------------------------------------------------------------------------
- // File: CutScene.cpp
- //
- // Desc: DirectShow sample code - simple interactive movie player. Plays
- // a movie or game cutscene in fullscreen mode. Supports simple user
- // input to enable ESC, spacebar, or ENTER to quit.
- //
- // Copyright (c) 1998-2001 Microsoft Corporation. All rights reserved.
- //------------------------------------------------------------------------------
-
-
- #include <dshow.h>
- #include <stdio.h>
- #include <atlbase.h>
-
- #include "cutscene.h"
-
- //
- // Constants
- //
- #define KEYBOARD_SAMPLE_FREQ 100 // Sample user input on an interval
- #define CUTSCENE_NAME TEXT("Cutscene Player Sample")
-
- //
- // Globals
- //
- static IGraphBuilder *pGB = NULL;
- static IMediaControl *pMC = NULL;
- static IVideoWindow *pVW = NULL;
- static IMediaEvent *pME = NULL;
-
- static HWND g_hwndMain=0;
- static BOOL g_bContinue=TRUE, g_bUserInterruptedPlayback=FALSE;
-
-
- //
- // Function prototypes
- //
- static HRESULT PlayMedia(LPTSTR lpszMovie, HINSTANCE hInstance);
- static HRESULT GetInterfaces(void);
- static HRESULT SetFullscreen(void);
- static BOOL CreateHiddenWindow( HINSTANCE hInstance, TCHAR *szFile );
- static LONG WINAPI WindowProc(HWND, UINT, WPARAM, LPARAM);
- static void CloseApp();
- static void CleanupInterfaces(void);
- static void Msg(TCHAR *szFormat, ...);
-
-
- //
- // Helper Macros (Jump-If-Failed, Log-If-Failed)
- //
- #define RELEASE(i) {if (i) i->Release(); i = NULL;}
-
- #define JIF(x) if (FAILED(hr=(x))) \
- {Msg(TEXT("FAILED(hr=0x%x) in ") TEXT(#x) TEXT("\n"), hr); goto CLEANUP;}
-
- #define LIF(x) if (FAILED(hr=(x))) \
- {Msg(TEXT("FAILED(hr=0x%x) in ") TEXT(#x) TEXT("\n"), hr); return hr;}
-
-
-
- HRESULT PlayCutscene(LPTSTR szMovie, HINSTANCE hInstance)
- {
- HRESULT hr;
-
- // Create the main hidden window to field keyboard input
- if (!CreateHiddenWindow(hInstance, szMovie))
- return E_FAIL;
-
- // Initialize COM
- if (FAILED(hr = CoInitialize(NULL)))
- return hr;
-
- // Get DirectShow interfaces
- if (FAILED(hr = GetInterfaces()))
- {
- CoUninitialize();
- return hr;
- }
-
- // Play the movie / cutscene
- hr = PlayMedia(szMovie, hInstance);
-
- // If the user interrupted playback and there was no other error,
- // return S_FALSE.
- if ((hr == S_OK) && g_bUserInterruptedPlayback)
- hr = S_FALSE;
-
- // Release DirectShow interfaces
- CleanupInterfaces();
- CoUninitialize();
-
- return hr;
- }
-
-
- BOOL CreateHiddenWindow( HINSTANCE hInstance, TCHAR *szFile )
- {
- TCHAR szTitle[MAX_PATH];
-
- // Set up and register window class
- WNDCLASS wc = {0};
- wc.lpfnWndProc = (WNDPROC) WindowProc;
- wc.hInstance = hInstance;
- wc.lpszClassName = CUTSCENE_NAME;
- if (!RegisterClass(&wc))
- return FALSE;
-
- wsprintf(szTitle, TEXT("%s: %s"), CUTSCENE_NAME, szFile);
-
- // Create a window of zero size that will serve as the sink for
- // keyboard input. If this media file has a video component, then
- // a second ActiveMovie window will be displayed in which the video
- // will be rendered. Setting keyboard focus on this application window
- // will allow the user to move the video window around the screen, make
- // it full screen, resize, center, etc. independent of the application
- // window. If the media file has only an audio component, then this will
- // be the only window created.
- g_hwndMain = CreateWindowEx(
- 0, CUTSCENE_NAME, szTitle,
- 0, // not visible
- 0, 0, 0, 0,
- NULL, NULL, hInstance, NULL );
-
- return (g_hwndMain != NULL);
- }
-
-
- LONG WINAPI WindowProc( HWND hWnd, UINT message,
- WPARAM wParam, LPARAM lParam )
- {
- switch( message )
- {
- // Monitor keystrokes for manipulating video window
- // and program options
- case WM_KEYDOWN:
- switch( wParam )
- {
- case VK_ESCAPE:
- case VK_SPACE:
- case VK_RETURN:
- g_bUserInterruptedPlayback = TRUE;
- CloseApp();
- break;
- }
- break;
-
- case WM_DESTROY:
- PostQuitMessage(0);
- return 0;
- }
-
- return (LONG) DefWindowProc(hWnd, message, wParam, lParam);
- }
-
-
-
- HRESULT GetInterfaces(void)
- {
- HRESULT hr = S_OK;
-
- // Instantiate filter graph interface
- JIF(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC,
- IID_IGraphBuilder, (void **)&pGB));
-
- // Get interfaces to control playback & screensize
- JIF(pGB->QueryInterface(IID_IMediaControl, (void **)&pMC));
- JIF(pGB->QueryInterface(IID_IVideoWindow, (void **)&pVW));
-
- // Get interface to allow the app to wait for completion of playback
- JIF(pGB->QueryInterface(IID_IMediaEventEx, (void **)&pME));
-
- return S_OK;
-
- // In case of failure, the helper macro jumps here
- CLEANUP:
- CleanupInterfaces();
- return(hr);
- }
-
-
- void CleanupInterfaces(void)
- {
- // Release the DirectShow interfaces
- RELEASE(pGB);
- RELEASE(pMC);
- RELEASE(pVW);
- RELEASE(pME);
-
- DestroyWindow(g_hwndMain);
- }
-
-
- void CloseApp()
- {
- // Stop playback and exit
- pMC->Stop();
- g_bContinue = FALSE;
-
- PostMessage(g_hwndMain, WM_CLOSE, 0, 0);
- }
-
-
-
- HRESULT PlayMedia(LPTSTR lpszMovie, HINSTANCE hInstance)
- {
- USES_CONVERSION;
-
- HRESULT hr = S_OK;
- WCHAR wFileName[MAX_PATH];
- BOOL bSleep=TRUE;
-
- wcscpy(wFileName, T2W(lpszMovie));
-
- // Allow DirectShow to create the FilterGraph for this media file
- hr = pGB->RenderFile(wFileName, NULL);
- if (FAILED(hr)) {
- Msg(TEXT("Failed(0x%08lx) in RenderFile(%s)!\r\n"), hr, lpszMovie);
- return hr;
- }
-
- // Set the message drain of the video window to point to our hidden
- // application window. This allows keyboard input to be transferred
- // to our main window for processing.
- //
- // If this is an audio-only or MIDI file, then put_MessageDrain will fail.
- //
- hr = pVW->put_MessageDrain((OAHWND) g_hwndMain);
- if (FAILED(hr))
- {
- Msg(TEXT("Failed(0x%08lx) to set message drain for %s.\r\n\r\n")
- TEXT("This sample is designed to play videos, but the file selected ")
- TEXT("has no video component."), hr, lpszMovie);
- return hr;
- }
-
- // Set fullscreen
- hr = SetFullscreen();
- if (FAILED(hr)) {
- Msg(TEXT("Failed(%08lx) to set fullscreen!\r\n"), hr);
- return hr;
- }
-
- // Display first frame of the movie
- hr = pMC->Pause();
- if (FAILED(hr)) {
- Msg(TEXT("Failed(%08lx) in Pause()!\r\n"), hr);
- return hr;
- }
-
- // Start playback
- hr = pMC->Run();
- if (FAILED(hr)) {
- Msg(TEXT("Failed(%08lx) in Run()!\r\n"), hr);
- return hr;
- }
-
- // Update state variables
- g_bContinue = TRUE;
-
- // Enter a loop of checking for events and sampling keyboard i6nput
- while (g_bContinue)
- {
- MSG msg;
- long lEventCode, lParam1, lParam2;
-
- // Reset sleep flag
- bSleep = TRUE;
-
- // Has there been a media event? Look for end of stream condition.
- if(E_ABORT != pME->GetEvent(&lEventCode, (LONG_PTR *) &lParam1,
- (LONG_PTR *) &lParam2, 0))
- {
- // Free the media event resources.
- hr = pME->FreeEventParams(lEventCode, lParam1, lParam2);
- if (FAILED(hr))
- {
- Msg(TEXT("Failed(%08lx) to free event params (%s)!\r\n"),
- hr, lpszMovie);
- }
-
- // Is this the end of the movie?
- if (lEventCode == EC_COMPLETE)
- {
- g_bContinue = FALSE;
- bSleep = FALSE;
- }
- }
-
- // Give system threads time to run (and don't sample user input madly)
- if (bSleep)
- Sleep(KEYBOARD_SAMPLE_FREQ);
-
- // Check and process window messages (like our keystrokes)
- while (PeekMessage (&msg, g_hwndMain, 0, 0, PM_REMOVE))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- }
-
- return hr;
- }
-
-
- HRESULT SetFullscreen(void)
- {
- HRESULT hr=S_OK;
- LONG lMode;
- static HWND hDrain=0;
-
- if (!pVW)
- return S_FALSE;
-
- // Read current state
- LIF(pVW->get_FullScreenMode(&lMode));
-
- if (lMode == 0) /* OAFALSE */
- {
- // Save current message drain
- LIF(pVW->get_MessageDrain((OAHWND *) &hDrain));
-
- // Set message drain to application main window
- LIF(pVW->put_MessageDrain((OAHWND) g_hwndMain));
-
- // Switch to full-screen mode
- lMode = -1; /* OATRUE */
- LIF(pVW->put_FullScreenMode(lMode));
- }
-
- return hr;
- }
-
-
- void Msg(TCHAR *szFormat, ...)
- {
- TCHAR szBuffer[512]; // Large buffer for very long filenames (like with HTTP)
-
- va_list pArgs;
- va_start(pArgs, szFormat);
- _vstprintf(szBuffer, szFormat, pArgs);
- va_end(pArgs);
-
- // This sample uses a simple message box to convey warning and error
- // messages. You may want to display a debug string or suppress messages
- // altogether, depending on your application.
- MessageBox(NULL, szBuffer, TEXT("PlayCutscene Error"), MB_OK);
- }
-
-
-