Initial commit: ROW Client source code

Game client codebase including:
- CharacterActionControl: Character and creature management
- GlobalScript: Network, items, skills, quests, utilities
- RYLClient: Main client application with GUI and event handlers
- Engine: 3D rendering engine (RYLGL)
- MemoryManager: Custom memory allocation
- Library: Third-party dependencies (DirectX, boost, etc.)
- Tools: Development utilities

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-29 16:24:34 +09:00
commit e067522598
5135 changed files with 1745744 additions and 0 deletions

View File

@@ -0,0 +1,674 @@
//------------------------------------------------------------------------------
// File: DDrawObj.cpp
//
// Desc: DirectShow sample code - implementation of DDrawObject class.
//
// Copyright (c) 1993-2001 Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------
#include <streams.h>
#include <windows.h>
#include "DDrawObj.h"
#include "VidPlay.h"
//
// CDDrawObject constructor
//
CDDrawObject::CDDrawObject(HWND hWndApp)
{
DbgLog((LOG_TRACE, 3, TEXT("CDDrawObject c-tor entered"))) ;
m_pDDObject = NULL ;
m_pPrimary = NULL ;
m_pBackBuff = NULL ;
// Default colors to be used for filling
m_dwScrnColor = RGB(0, 0, 0) ;
m_dwVideoKeyColor = RGB(255, 0, 255) ;
// Rects for the screen area and video area
SetRect(&m_RectScrn, 0, 0, 0, 0) ;
SetRect(&m_RectVideo, 0, 0, 0, 0) ;
// some flags, count, messages for buffer flipping
m_bInExclMode = FALSE ;
m_iCount = 0 ;
m_bFrontBuff = TRUE ;
m_szFrontMsg = TEXT("Front Buffer" );
m_szBackMsg = TEXT("Back Buffer" );
m_szDirection = TEXT("Press the 'Arrow' keys to move the ball. Hit 'Esc' to stop playback." );
// Create brush and pen for drawing the filled ball
LOGBRUSH lb ;
lb.lbStyle = BS_HATCHED ;
lb.lbColor = RGB(0, 255, 0) ;
lb.lbHatch = HS_CROSS ;
m_hBrush = CreateBrushIndirect(&lb) ;
ASSERT(NULL != m_hBrush) ;
m_hPen = CreatePen(PS_SOLID, 2, RGB(0, 0, 255)) ;
ASSERT(NULL != m_hPen) ;
HRESULT hr=S_OK ;
m_pOverlayCallback = (IDDrawExclModeVideoCallback *) new COverlayCallback(this, hWndApp, &hr) ;
ASSERT(SUCCEEDED(hr)) ;
m_bOverlayVisible = FALSE ; // don't draw color key until it's OK-ed by OverlayMixer
}
//
// CDDrawObject destructor
//
CDDrawObject::~CDDrawObject(void)
{
DbgLog((LOG_TRACE, 3, TEXT("CDDrawObject d-tor entered"))) ;
// Let go of the overlay notification callback object now
if (m_pOverlayCallback)
m_pOverlayCallback->Release() ; // done with callback object now
// delete the pen and brush we created for drawing the ball
if (m_hPen)
DeleteObject(m_hPen) ;
if (m_hBrush)
DeleteObject(m_hBrush) ;
if (m_pBackBuff)
m_pBackBuff->Release() ;
if (m_pPrimary)
m_pPrimary->Release() ;
if (m_pDDObject)
m_pDDObject->Release() ;
DbgLog((LOG_TRACE, 3, TEXT("CDDrawObject d-tor exiting..."))) ;
}
//
// CDDrawObject::Initialize(): Just creates a DDraw object.
//
BOOL CDDrawObject::Initialize(HWND hWndApp)
{
DbgLog((LOG_TRACE, 5, TEXT("CDDrawObject::Initialize() entered"))) ;
HRESULT hr = DirectDrawCreate(NULL, &m_pDDObject, NULL) ;
if (FAILED(hr) || NULL == m_pDDObject)
{
MessageBox(hWndApp,
TEXT("Can't create a DirectDraw object.\nPress OK to end the app."),
TEXT("Error"), MB_OK | MB_ICONSTOP) ;
return FALSE ;
}
return TRUE;
}
#define SCRN_WIDTH 800
#define SCRN_HEIGHT 600
#define SCRN_BITDEPTH 8
//
// CDDrawObject::StartExclusiveMode(): Gets into fullscreen exclusive mode, sets
// display mode to 800x600x8, creates a flipping primary surface with one back
// buffer, gets the surface size and inits some variables.
//
// NOTE: Please don't bother about the "#ifndef NOFLIP"s. They were there
// for testing.
//
HRESULT CDDrawObject::StartExclusiveMode(HWND hWndApp)
{
DbgLog((LOG_TRACE, 5, TEXT("CDDrawObject::StartExclusiveMode() entered"))) ;
HRESULT hr ;
DDSURFACEDESC ddsd ;
DDSCAPS ddscaps ;
if (! Initialize(hWndApp) )
return E_FAIL ;
// Get into fullscreen exclusive mode
#ifndef NOFLIP
hr = m_pDDObject->SetCooperativeLevel(hWndApp,
DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT) ;
if (FAILED(hr))
{
MessageBox(hWndApp,
TEXT("SetCooperativeLevel() failed to go into exclusive mode"),
TEXT("Error"), MB_OK | MB_ICONSTOP) ;
return hr ;
}
#else
hr = m_pDDObject->SetCooperativeLevel(hWndApp, DDSCL_NORMAL) ;
if (FAILED(hr))
{
MessageBox(hWndApp,
TEXT("SetCooperativeLevel() failed to go into normal mode"),
TEXT("Error"), MB_OK | MB_ICONSTOP) ;
return hr ;
}
#endif // NOFLIP
#ifndef NOFLIP
hr = m_pDDObject->SetDisplayMode(SCRN_WIDTH, SCRN_HEIGHT, SCRN_BITDEPTH) ;
if (FAILED(hr))
{
DbgLog((LOG_ERROR, 0, TEXT("ERROR: SetDisplayMode failed (Error 0x%lx)"), hr)) ;
MessageBox(hWndApp, TEXT("SetDisplayMode(640, 480, 8) failed"),
TEXT("Error"), MB_OK | MB_ICONSTOP) ;
return hr ;
}
#endif // NOFLIP
// Create the primary surface with 1 back buffer
ZeroMemory(&ddsd, sizeof(ddsd)) ;
ddsd.dwSize = sizeof(ddsd) ;
#ifndef NOFLIP
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT ;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
DDSCAPS_FLIP |
DDSCAPS_COMPLEX ;
ddsd.dwBackBufferCount = 1 ;
#else
ddsd.dwFlags = DDSD_CAPS ;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE ;
#endif // NOFLIP
hr = m_pDDObject->CreateSurface(&ddsd, &m_pPrimary, NULL) ;
if (FAILED(hr))
{
#ifndef NOFLIP
MessageBox(hWndApp, TEXT("CreateSurface(Primary, flip(1), complex) failed"),
TEXT("Error"), MB_OK | MB_ICONSTOP) ;
#else
MessageBox(hWndApp, TEXT("CreateSurface(Primary, noflip, no backbuffer) failed"),
TEXT("Error"), MB_OK | MB_ICONSTOP) ;
#endif // NOFLIP
return hr ;
}
#ifndef NOFLIP
// Get a pointer to the back buffer
ddscaps.dwCaps = DDSCAPS_BACKBUFFER ;
hr = m_pPrimary->GetAttachedSurface(&ddscaps, &m_pBackBuff) ;
if (FAILED(hr))
{
MessageBox(hWndApp, TEXT("GetAttachedSurface() failed to get back buffer"),
TEXT("Error"), MB_OK | MB_ICONSTOP) ;
return hr ;
}
#endif // NOFLIP
// Get the screen size and save it as a rect
ZeroMemory(&ddsd, sizeof(ddsd)) ;
ddsd.dwSize = sizeof(ddsd) ;
hr = m_pPrimary->GetSurfaceDesc(&ddsd) ;
if (! (SUCCEEDED(hr) && (ddsd.dwFlags & DDSD_WIDTH) && (ddsd.dwFlags & DDSD_HEIGHT)) )
{
MessageBox(hWndApp, TEXT("GetSurfaceDesc() failed to get surface width & height"),
TEXT("Error"), MB_OK | MB_ICONSTOP) ;
return hr ;
}
SetRect(&m_RectScrn, 0, 0, ddsd.dwWidth, ddsd.dwHeight) ;
// Reset some buffer drawing flags, values etc.
m_iCount = 0 ;
m_bFrontBuff = TRUE ;
m_bInExclMode = TRUE ;
return S_OK ;
}
//
// CDDrawObject::StopExclusiveMode(): Releases primary buffer, exits
// exclusive mode, resets some variables/flags.
//
HRESULT CDDrawObject::StopExclusiveMode(HWND hWndApp)
{
DbgLog((LOG_TRACE, 5, TEXT("CDDrawObject::StopExclusiveMode() entered"))) ;
HRESULT hr ;
if (m_pBackBuff)
{
hr = m_pBackBuff->Release() ; // release back buffer
m_pBackBuff = NULL ; // no back buffer anymore
}
#ifndef NOFLIP
if (m_pDDObject)
{
// Restore display to previous mode (set with SetDisplayMode())
hr = m_pDDObject->RestoreDisplayMode();
if (FAILED(hr))
{
DbgLog((LOG_ERROR, 0, TEXT("ERROR: RestoreDisplayMode failed (Error 0x%lx)"), hr)) ;
MessageBox(hWndApp, TEXT("RestoreDisplayMode failed"),
TEXT("Error"), MB_OK | MB_ICONSTOP) ;
}
}
#endif // NOFLIP
// Release the primary surface (and attached buffer with it)
if (m_pPrimary)
{
hr = m_pPrimary->Release() ; // release primary surface
m_pPrimary = NULL ;
}
// Get out of fullscreen exclusive mode
if (m_pDDObject)
{
hr = m_pDDObject->SetCooperativeLevel(hWndApp, DDSCL_NORMAL) ;
if (FAILED(hr))
{
MessageBox(hWndApp,
TEXT("SetCooperativeLevel() failed to go back to normal mode"),
TEXT("Error"), MB_OK | MB_ICONSTOP) ;
return hr ;
}
m_pDDObject->Release() ; // now release the DDraw object
m_pDDObject = NULL ; // no more DDraw object
}
// Reset the color key and screen, video rects.
m_dwVideoKeyColor = RGB(255, 0, 255) ;
SetRect(&m_RectScrn, 0, 0, 0, 0) ;
SetRect(&m_RectVideo, 0, 0, 0, 0) ;
m_bInExclMode = FALSE ;
return S_OK ;
}
//
// CDDrawObject::DrawOnSurface(): Private method to draw stuff on back buffer
//
void CDDrawObject::DrawOnSurface(LPDIRECTDRAWSURFACE pSurface)
{
DbgLog((LOG_TRACE, 5, TEXT("CDDrawObject::DrawOnSurface() entered"))) ;
HDC hDC ;
TCHAR achBuffer[30] ;
if (DD_OK == pSurface->GetDC(&hDC))
{
// write fonr/back to show buffer flipping
SetBkColor(hDC, RGB(0, 0, 255)) ;
SetTextColor(hDC, RGB(255, 255, 0)) ;
wsprintf(achBuffer, TEXT(" %-12s: %6.6d "),
m_bFrontBuff ? m_szFrontMsg : m_szBackMsg, m_iCount) ;
TextOut(hDC, 20, 10, achBuffer, lstrlen(achBuffer)) ;
// Write the instructions
SetBkColor(hDC, RGB(0, 0, 0)) ;
SetTextColor(hDC, RGB(0, 255, 255)) ;
TextOut(hDC, m_RectScrn.left + 100, m_RectScrn.bottom - 20, m_szDirection, lstrlen(m_szDirection)) ;
// Draw the ball on screen now
HBRUSH hBrush = (HBRUSH) SelectObject(hDC, m_hBrush) ; // select special brush
HPEN hPen = (HPEN) SelectObject(hDC, m_hPen) ; // select special pen
Ellipse(hDC, m_iBallCenterX - BALL_RADIUS, m_iBallCenterY - BALL_RADIUS,
m_iBallCenterX + BALL_RADIUS, m_iBallCenterY + BALL_RADIUS) ;
SelectObject(hDC, hBrush) ; // restore original brush
SelectObject(hDC, hPen) ; // restore original pen
pSurface->ReleaseDC(hDC) ; // done now; let go of the DC
}
}
//
// CDDrawObject::ConvertColorRefToPhysColor(): Converts a COLORREF to a
// DWORD physical color value based on current display mode.
//
// NOTE: This method is useful ONLY if you want to get the COLORREF from
// OverlayMixer (rather than the physical color as a DWORD) and convert
// it yourself. But OverlayMixer does it for you anyway; so the utility
// of this method is quite minimal.
//
HRESULT CDDrawObject::ConvertColorRefToPhysColor(COLORREF rgb, DWORD *pdwPhysColor)
{
HRESULT hr ;
COLORREF rgbCurr ;
HDC hDC ;
DDSURFACEDESC ddsd ;
ASSERT(rgb != CLR_INVALID) ;
// use GDI SetPixel to color match for us
hr = m_pBackBuff->GetDC(&hDC) ;
if (DD_OK != hr)
{
DbgLog((LOG_ERROR, 0, TEXT("m_pBackBuff->GetDC() failed (Error 0x%lx)"), hr)) ;
return hr ;
}
rgbCurr = GetPixel(hDC, 0, 0) ; // save current pixel value
SetPixel(hDC, 0, 0, rgb) ; // set our value
m_pBackBuff->ReleaseDC(hDC) ;
// now lock the surface so we can read back the converted color
ZeroMemory(&ddsd, sizeof(ddsd)) ;
ddsd.dwSize = sizeof(ddsd) ;
while (DDERR_WASSTILLDRAWING == (hr = m_pBackBuff->Lock(NULL, &ddsd, 0, NULL))) // until unlocked...
; // ...just wait
if (DD_OK == hr)
{
// get DWORD
*pdwPhysColor = *(DWORD *) ddsd.lpSurface ;
// mask it to bpp
if (ddsd.ddpfPixelFormat.dwRGBBitCount < 32)
*pdwPhysColor &= (1 << ddsd.ddpfPixelFormat.dwRGBBitCount) - 1 ;
m_pBackBuff->Unlock(NULL) ;
}
else
{
DbgLog((LOG_ERROR, 0, TEXT("m_pBackBuff->Lock() failed (Error 0x%lx)"), hr)) ;
return hr ;
}
// now restote the pixel to the color that was there
hr = m_pBackBuff->GetDC(&hDC) ;
if (DD_OK != hr)
{
DbgLog((LOG_ERROR, 0, TEXT("m_pBackBuff->GetDC() failed (Error 0x%lx)"), hr)) ;
return hr ;
}
SetPixel(hDC, 0, 0, rgbCurr) ;
m_pBackBuff->ReleaseDC(hDC) ;
return S_OK ;
}
#if 0
//
// CDDrawObject::SetColorKey(): Creates a DWORD physical color out COLORREF.
//
// NOTE: This method is useful only if you want to do the conversion. We have
// defined an inline version in ddrawobj.h file.
//
HRESULT CDDrawObject::SetColorKey(COLORKEY *pColorKey)
{
if (NULL == pColorKey)
return E_INVALIDARG ;
DWORD dwPhysColor ;
HRESULT hr = ConvertColorRefToPhysColor(pColorKey->LowColorValue, &dwPhysColor) ;
if (FAILED(hr))
return hr ;
m_dwVideoKeyColor = dwPhysColor ;
return S_OK ;
}
#endif // #if 0
//
// CDDrawObject::FillSurface(): Private method to fill the back buffer with black
// color and put the color key in teh video area.
//
// NOTE: Re-filling the back buffer every time is required ONLY IF the video
// position keeps changing. Otherwise setting it once should be fine.
//
HRESULT CDDrawObject::FillSurface(IDirectDrawSurface *pDDSurface)
{
DbgLog((LOG_TRACE, 5, TEXT("CDDrawObject::FillSurface() entered"))) ;
if (NULL == pDDSurface)
return E_INVALIDARG ;
// Repaint the whole specified surface
HRESULT hr ;
DDBLTFX ddFX ;
ZeroMemory(&ddFX, sizeof(ddFX)) ;
ddFX.dwSize = sizeof(ddFX) ;
ddFX.dwFillColor = m_dwScrnColor ;
hr = pDDSurface->Blt(&m_RectScrn, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddFX) ;
if (FAILED(hr))
{
DbgLog((LOG_ERROR, 0, TEXT("pDDSurface->Blt for screen failed (Error 0x%lx)"), hr)) ;
DbgLog((LOG_ERROR, 0, TEXT("Destination Rect: (%ld, %ld, %ld, %ld), Color = 0x%lx"),
m_RectScrn.left, m_RectScrn.top, m_RectScrn.right, m_RectScrn.bottom, m_dwScrnColor)) ;
return hr ;
}
// Draw color key on the video area of given surface, ONLY IF we are supposed
// to paint color key in the video area.
if (m_bOverlayVisible)
{
ddFX.dwFillColor = m_dwVideoKeyColor ;
hr = pDDSurface->Blt(&m_RectVideo, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddFX) ;
if (FAILED(hr))
{
DbgLog((LOG_ERROR, 0, TEXT("pDDSurface->Blt for video failed (Error 0x%lx)"), hr)) ;
DbgLog((LOG_ERROR, 0, TEXT("Destination Rect: (%ld, %ld, %ld, %ld), Color = 0x%lx"),
m_RectVideo.left, m_RectVideo.top, m_RectVideo.right, m_RectVideo.bottom,
m_dwVideoKeyColor)) ;
return hr ;
}
}
else
DbgLog((LOG_TRACE, 5, TEXT("Color keying of video area skipped"))) ;
return S_OK ;
}
//
// CDDrawObject::UpdateAndFlipSurfaces(): Prepares the back buffer and flips.
//
HRESULT CDDrawObject::UpdateAndFlipSurfaces(void)
{
DbgLog((LOG_TRACE, 5, TEXT("CDDrawObject::UpdateAndFlipSurfaces() entered"))) ;
// Draw screen and color key on the current back buffer
HRESULT hr = FillSurface(m_pBackBuff) ;
if (FAILED(hr))
{
DbgLog((LOG_ERROR, 1, TEXT("UpdateAndFlipSurfaces() skipped as FillSurface() failed"), hr)) ;
return hr ; // or return S_OK??
}
IncCount() ; // increment flip count first
m_bFrontBuff = !m_bFrontBuff ; // toggle flag
DrawOnSurface(m_pBackBuff) ; // draw next text on the back buffer
// Keep trying to flip the buffers until successful
while (1)
{
hr = m_pPrimary->Flip(NULL, 0) ; // flip the surfaces
if (DD_OK == hr) // success!!
{
break ;
}
if (DDERR_SURFACELOST == hr) // surface lost; try to restore
{
DbgLog((LOG_TRACE, 5, TEXT("DirectDraw surface was lost. Trying to restore..."))) ;
hr = m_pPrimary->Restore() ;
if (DD_OK != hr) // couldn't restore surface
{
DbgLog((LOG_ERROR, 0, TEXT("IDirectDrawSurface::Restore() failed (Error 0x%lx)"), hr)) ;
break ;
}
}
if (DDERR_WASSTILLDRAWING != hr) // some weird error -- bail out
{
DbgLog((LOG_ERROR, 0, TEXT("IDirectDrawSurface::Flip() failed (Error 0x%lx)"), hr)) ;
break ;
}
}
return hr ;
}
//
// CDDrawObject::SetVideoPosition(): Receives the video position in terms of screen
// coordinates.
//
void CDDrawObject::SetVideoPosition(DWORD dwVideoLeft, DWORD dwVideoTop,
DWORD dwVideoWidth, DWORD dwVideoHeight)
{
DbgLog((LOG_TRACE, 5, TEXT("CDDrawObject::SetVideoPosition() entered"))) ;
SetRect(&m_RectVideo, dwVideoLeft, dwVideoTop, dwVideoLeft + dwVideoWidth,
dwVideoTop + dwVideoHeight) ;
}
//
// CDDrawObject::SetBallPosition(): Uses the video position to initialize the ball's
// position to the center of the video.
//
void CDDrawObject::SetBallPosition(DWORD dwVideoLeft, DWORD dwVideoTop,
DWORD dwVideoWidth, DWORD dwVideoHeight)
{
DbgLog((LOG_TRACE, 5, TEXT("CDDrawObject::SetBallPosition() entered"))) ;
// Place the ball at the middle of video on start
m_iBallCenterX = dwVideoLeft + dwVideoWidth / 2 ;
m_iBallCenterY = dwVideoTop + dwVideoHeight / 2 ;
}
//
// CDDrawObject::MoveBallPosition(): Moves the ball L/R/U/D and keeps it within
// the video area..
//
void CDDrawObject::MoveBallPosition(int iDirX, int iDirY)
{
DbgLog((LOG_TRACE, 5, TEXT("CDDrawObject::MoveBallPosition(%d, %d) entered"),
iDirX, iDirY)) ;
m_iBallCenterX += iDirX ;
m_iBallCenterY += iDirY ;
// Keep the ball inside the video rect
if (m_iBallCenterX < m_RectVideo.left + BALL_RADIUS)
m_iBallCenterX = m_RectVideo.left + BALL_RADIUS ;
else if (m_iBallCenterX > m_RectVideo.right - BALL_RADIUS)
m_iBallCenterX = m_RectVideo.right - BALL_RADIUS ;
if (m_iBallCenterY < m_RectVideo.top + BALL_RADIUS)
m_iBallCenterY = m_RectVideo.top + BALL_RADIUS ;
else if (m_iBallCenterY > m_RectVideo.bottom - BALL_RADIUS)
m_iBallCenterY = m_RectVideo.bottom - BALL_RADIUS ;
}
//
// Overlay Callback object implementation
//
COverlayCallback::COverlayCallback(CDDrawObject *pDDrawObj, HWND hWndApp, HRESULT *phr) :
CUnknown("Overlay Callback Object", NULL, phr),
m_pDDrawObj(pDDrawObj),
m_hWndApp(hWndApp)
{
DbgLog((LOG_TRACE, 5, TEXT("COverlayCallback::COverlayCallback() entered"))) ;
ASSERT(m_pDDrawObj) ;
AddRef() ; // increment ref count for itself
}
COverlayCallback::~COverlayCallback()
{
DbgLog((LOG_TRACE, 5, TEXT("COverlayCallback::~COverlayCallback() entered"))) ;
}
HRESULT COverlayCallback::OnUpdateOverlay(BOOL bBefore,
DWORD dwFlags,
BOOL bOldVisible,
const RECT *prcSrcOld,
const RECT *prcDestOld,
BOOL bNewVisible,
const RECT *prcSrcNew,
const RECT *prcDestNew)
{
DbgLog((LOG_TRACE, 5, TEXT("COverlayCallback::OnUpdateOverlay(%s, ...) entered"),
bBefore ? "TRUE" : "FALSE")) ;
if (NULL == m_pDDrawObj)
{
DbgLog((LOG_ERROR, 1, TEXT("ERROR: NULL DDraw object pointer was specified"))) ;
return E_POINTER ;
}
if (bBefore) // overlay is going to be updated
{
DbgLog((LOG_TRACE, 5, TEXT("Just turn off color keying and return"))) ;
m_pDDrawObj->SetOverlayState(FALSE) ; // don't paint color key in video's position
#ifndef NOFLIP
m_pDDrawObj->UpdateAndFlipSurfaces() ; // flip the surface so that video doesn't show anymore
#endif // NOFLIP
return S_OK ;
}
//
// After overlay has been updated. Turn on/off overlay color keying based on
// flags and use new source/dest position etc.
//
if (dwFlags & (AM_OVERLAY_NOTIFY_VISIBLE_CHANGE |
AM_OVERLAY_NOTIFY_SOURCE_CHANGE |
AM_OVERLAY_NOTIFY_DEST_CHANGE)) // it's a valid flag
m_pDDrawObj->SetOverlayState(bNewVisible) ; // paint/don't paint color key based on param
if (dwFlags & AM_OVERLAY_NOTIFY_VISIBLE_CHANGE) // overlay visibility state change
{
DbgLog((LOG_TRACE, 5, TEXT(".._NOTIFY_VISIBLE_CHANGE from %s to %s"),
bOldVisible ? "TRUE" : "FALSE", bNewVisible ? "TRUE" : "FALSE")) ;
}
if (dwFlags & AM_OVERLAY_NOTIFY_SOURCE_CHANGE) // overlay source rect change
{
DbgLog((LOG_TRACE, 5, TEXT(".._NOTIFY_SOURCE_CHANGE from (%ld, %ld, %ld, %ld) to (%ld, %ld, %ld, %ld)"),
prcSrcOld->left, prcSrcOld->top, prcSrcOld->right, prcSrcOld->bottom,
prcSrcNew->left, prcSrcNew->top, prcSrcNew->right, prcSrcNew->bottom)) ;
}
if (dwFlags & AM_OVERLAY_NOTIFY_DEST_CHANGE) // overlay destination rect change
{
DbgLog((LOG_TRACE, 5, TEXT(".._NOTIFY_DEST_CHANGE from (%ld, %ld, %ld, %ld) to (%ld, %ld, %ld, %ld)"),
prcDestOld->left, prcDestOld->top, prcDestOld->right, prcDestOld->bottom,
prcDestNew->left, prcDestNew->top, prcDestNew->right, prcDestNew->bottom)) ;
m_pDDrawObj->SetVideoPosition(prcDestNew->left, prcDestNew->top,
RECTWIDTH(*prcDestNew), RECTHEIGHT(*prcDestNew)) ;
}
return S_OK ;
}
HRESULT COverlayCallback::OnUpdateColorKey(COLORKEY const *pKey,
DWORD dwColor)
{
DbgLog((LOG_TRACE, 5, TEXT("COverlayCallback::OnUpdateColorKey(.., 0x%lx) entered"), dwColor)) ;
return S_OK ;
}
HRESULT COverlayCallback::OnUpdateSize(DWORD dwWidth, DWORD dwHeight,
DWORD dwARWidth, DWORD dwARHeight)
{
DbgLog((LOG_TRACE, 5, TEXT("COverlayCallback::OnUpdateSize(%lu, %lu, %lu, %lu) entered"),
dwWidth, dwHeight, dwARWidth, dwARHeight)) ;
PostMessage(m_hWndApp, WM_SIZE_CHANGE, 0, 0) ;
return S_OK ;
}

View File

@@ -0,0 +1,115 @@
//------------------------------------------------------------------------------
// File: DDrawObj.h
//
// Desc: DirectShow sample code - DDraw Object class header file.
//
// Copyright (c) 1993-2001 Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------
// #define NOFLIP 1 /* for debugging */
// Define ball radius
#define BALL_RADIUS 40
#define BALL_STEP 4
//
// Some macros
//
#define RECTWIDTH(rect) ((rect).right - (rect).left)
#define RECTHEIGHT(rect) ((rect).bottom - (rect).top)
// forward declaration
class COverlayCallback ;
//
// DDraw object class to paint color key, flip etc etc.
//
class CDDrawObject {
public: // public methods for Windows structure to call
CDDrawObject(HWND hWndApp) ;
~CDDrawObject(void) ;
BOOL Initialize(HWND hWndApp) ;
HRESULT StartExclusiveMode(HWND hWndApp) ;
HRESULT StopExclusiveMode(HWND hWndApp) ;
HRESULT UpdateAndFlipSurfaces(void) ;
void SetVideoPosition(DWORD dwVideoLeft, DWORD dwVideoTop,
DWORD dwVideoWidth, DWORD dwVideoHeight) ;
void SetBallPosition(DWORD dwVideoLeft, DWORD dwVideoTop,
DWORD dwVideoWidth, DWORD dwVideoHeight) ;
void MoveBallPosition(int iDirX, int iDirY) ;
inline void SetColorKey(DWORD dwColorKey) { m_dwVideoKeyColor = dwColorKey ; } ;
inline void GetScreenRect(RECT *pRect) { *pRect = m_RectScrn ; } ;
inline BOOL IsInExclusiveMode(void) { return m_bInExclMode ; } ;
inline LPDIRECTDRAW GetDDObject(void) { return m_pDDObject ; } ;
inline LPDIRECTDRAWSURFACE GetDDPrimary(void) { return m_pPrimary ; } ;
inline void SetOverlayState(BOOL bState) { m_bOverlayVisible = bState ; } ;
inline IDDrawExclModeVideoCallback * GetCallbackInterface(void) { return m_pOverlayCallback ; } ;
private: // private helper methods for the class' own use
HRESULT FillSurface(IDirectDrawSurface *pDDSurface) ;
void DrawOnSurface(LPDIRECTDRAWSURFACE pSurface) ;
HRESULT ConvertColorRefToPhysColor(COLORREF rgb, DWORD *pdwPhysColor) ;
inline DWORD GetColorKey(DWORD dwColorKey) { return m_dwVideoKeyColor ; } ;
inline void IncCount(void) { m_iCount++ ; } ;
inline int GetCount(void) { return m_iCount ; } ;
private: // internal state info
LPDIRECTDRAW m_pDDObject ; // DirectDraw interface
LPDIRECTDRAWSURFACE m_pPrimary ; // primary surface
LPDIRECTDRAWSURFACE m_pBackBuff ; // back buffer attached to primary
BOOL m_bInExclMode ; // Are we in exclusive mode now?
RECT m_RectScrn ; // whole screen as a rect
RECT m_RectVideo ; // current video position as rect
DWORD m_dwScrnColor ; // physical color for surface filling
DWORD m_dwVideoKeyColor ; // physical color for color keying video area
int m_iCount ; // flip count
int m_iBallCenterX ; // X-coord of ball's center
int m_iBallCenterY ; // Y-coord of ball's center
BOOL m_bFrontBuff ; // draw on front (or back) buffer?
LPTSTR m_szFrontMsg ; // front surface string ("Front Buffer")
LPTSTR m_szBackMsg ; // back surface string ("Back Buffer")
LPTSTR m_szDirection ; // Direction string for users
HPEN m_hPen ; // pen for drawing outline of the ball
HBRUSH m_hBrush ; // brush for filling the ball
BOOL m_bOverlayVisible ; // is overlay visible?
IDDrawExclModeVideoCallback *m_pOverlayCallback ; // overlay callback handler interface
} ;
//
// Overlay callback handler object class
//
class COverlayCallback : public CUnknown, public IDDrawExclModeVideoCallback
{
public:
COverlayCallback(CDDrawObject *pDDrawObj, HWND hWndApp, HRESULT *phr) ;
~COverlayCallback() ;
DECLARE_IUNKNOWN
//
// IDDrawExclModeVideoCallback interface methods
//
STDMETHODIMP OnUpdateOverlay(BOOL bBefore,
DWORD dwFlags,
BOOL bOldVisible,
const RECT *prcSrcOld,
const RECT *prcDestOld,
BOOL bNewVisible,
const RECT *prcSrcNew,
const RECT *prcDestNew) ;
STDMETHODIMP OnUpdateColorKey(COLORKEY const *pKey,
DWORD dwColor) ;
STDMETHODIMP OnUpdateSize(DWORD dwWidth, DWORD dwHeight,
DWORD dwARWidth, DWORD dwARHeight) ;
private:
CDDrawObject *m_pDDrawObj ;
HWND m_hWndApp ;
} ;

View File

@@ -0,0 +1,871 @@
//------------------------------------------------------------------------------
// File: DDrawXcl.cpp
//
// Desc: DirectShow sample code - DDraw Exclusive Mode Video Playback
// test/sample application.
//
// Copyright (c) 1993-2001 Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------
#include <streams.h>
#include <windows.h>
#include <commdlg.h>
#include <DVDEvCod.h>
#include "VidPlay.h"
#include "DDrawObj.h"
#include "DDrawXcl.h"
//
// WinMain(): Entry point to our sample app.
//
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
MSG msg ;
HACCEL hAccelTable ;
DbgInitialise(hInstance) ;
CoInitialize(NULL) ;
ghInstance = hInstance ;
LoadString(ghInstance, IDS_APP_TITLE, gszAppTitle, 100) ;
LoadString(ghInstance, IDS_APP_NAME, gszAppName, 10) ;
if (! InitApplication() )
{
DbgTerminate() ;
return FALSE ;
}
if (! InitInstance(nCmdShow) )
{
DbgTerminate() ;
return FALSE ;
}
hAccelTable = LoadAccelerators(hInstance, gszAppName) ;
//
// Create a DDraw object and init it
//
gpDDrawObj = new CDDrawObject(ghWndApp) ;
if (NULL == gpDDrawObj)
{
DbgTerminate() ;
return FALSE ;
}
gpPlayer = NULL ; // Init Video playback object pointer to NULL
geVideoType = Unspecified ; // no video type specified on start up
gbAppActive = TRUE ; // app is activated on start up
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
if (! TranslateAccelerator(msg.hwnd, hAccelTable, &msg) )
{
TranslateMessage(&msg) ;
DispatchMessage(&msg) ;
}
}
//
// Release the video playback object, if any
//
if (gpPlayer)
delete gpPlayer ;
//
// Release DDraw now
//
delete gpDDrawObj ;
CoUninitialize() ;
DbgTerminate() ;
return (int) (msg.wParam) ;
}
//
// InitApplication(): Registers the class if no other instance of this app is
// already running.
//
BOOL InitApplication(void)
{
DbgLog((LOG_TRACE, 5, TEXT("App's InitApplication() entered"))) ;
WNDCLASSEX wc ;
// Win32 will always set hPrevInstance to NULL, so lets check
// things a little closer. This is because we only want a single
// version of this app to run at a time
ghWndApp = FindWindow (gszAppName, gszAppTitle) ;
if (ghWndApp) {
// We found another version of ourself. Lets defer to it:
if (IsIconic(ghWndApp)) {
ShowWindow(ghWndApp, SW_RESTORE);
}
SetForegroundWindow(ghWndApp);
// If this app actually had any functionality, we would
// also want to communicate any action that our 'twin'
// should now perform based on how the user tried to
// execute us.
return FALSE;
}
// Register the app main window class
wc.cbSize = sizeof(wc) ;
wc.style = CS_HREDRAW | CS_VREDRAW ;
wc.lpfnWndProc = (WNDPROC) WndProc ;
wc.cbClsExtra = 0 ;
wc.cbWndExtra = 0 ;
wc.hInstance = ghInstance ;
wc.hIcon = LoadIcon(ghInstance, gszAppName) ;
wc.hCursor = LoadCursor(NULL, IDC_ARROW) ;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1) ;
wc.lpszMenuName = gszAppName ;
wc.lpszClassName = gszAppName ;
wc.hIconSm = NULL ;
if (0 == RegisterClassEx(&wc))
{
DbgLog((LOG_ERROR, 0,
TEXT("ERROR: RegisterClassEx() for app class failed (Error %ld)"),
GetLastError())) ;
return FALSE ;
}
return TRUE ;
}
//
// InitInstance(): Starts this instance of the app (creates the window).
//
BOOL InitInstance(int nCmdShow)
{
DbgLog((LOG_TRACE, 5, TEXT("App's InitInstance() entered"))) ;
ghWndApp = CreateWindowEx(0, gszAppName, gszAppTitle,
WS_OVERLAPPEDWINDOW,
0, 0,
DEFAULT_WIDTH, DEFAULT_HEIGHT,
NULL, NULL, ghInstance, NULL);
if (! ghWndApp ) {
return FALSE ;
}
ShowWindow(ghWndApp, nCmdShow);
UpdateWindow(ghWndApp) ;
return TRUE ;
}
//
// MenuProc(): Handles menu choices picked by the user.
//
LRESULT CALLBACK MenuProc(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
HMENU hMenu = GetMenu(hWnd) ;
int wmId = LOWORD(wParam);
// int wmEvent = HIWORD(wParam);
//Parse the menu selections:
switch (wmId) {
case IDM_SELECTDVD:
if (FileSelect(hWnd, DVD)) // selection changed
{
CheckMenuItem(hMenu, IDM_SELECTDVD, MF_CHECKED) ;
CheckMenuItem(hMenu, IDM_SELECTFILE, MF_UNCHECKED) ;
}
break;
case IDM_SELECTFILE:
if (FileSelect(hWnd, File)) // selection changed
{
CheckMenuItem(hMenu, IDM_SELECTDVD, MF_UNCHECKED) ;
CheckMenuItem(hMenu, IDM_SELECTFILE, MF_CHECKED) ;
}
break;
case IDM_ABOUT:
DialogBox(ghInstance, TEXT("AboutBox"), ghWndApp, (DLGPROC) About);
break;
case IDM_EXIT:
DestroyWindow(ghWndApp);
break;
case IDM_STARTPLAY:
if (StartPlay(hWnd)) // playback started successfully
gbAppActive = TRUE ; // if we are playing, we must be active
else // playback failed due to some reason
MessageBox(hWnd,
STR_EXCLUSIVE_MODE_FAILURE,
TEXT("Error"), MB_OK | MB_ICONINFORMATION) ;
break;
default:
break ;
}
return 0 ;
}
//
// FileSelect(): Lets the user specify the file to play.
//
BOOL FileSelect(HWND hWnd, VIDEO_TYPE eType)
{
DbgLog((LOG_TRACE, 5, TEXT("App's FileSelect(%s) entered"),
DVD == eType ? "DVD" : "File")) ;
OPENFILENAME ofn ;
TCHAR achFileName[MAX_PATH] ;
// Init the filename buffer with either a filename or *.ifo
if (DVD == eType)
lstrcpy(achFileName, TEXT("*.ifo")) ;
else
lstrcpy(achFileName, TEXT("*.avi")) ;
ZeroMemory(&ofn, sizeof(OPENFILENAME)) ;
ofn.lStructSize = sizeof(OPENFILENAME) ;
ofn.hwndOwner = hWnd ;
if (DVD == eType)
{
ofn.lpstrTitle = TEXT("Select DVD-Video Volume\0") ;
ofn.lpstrFilter = TEXT("IFO Files\0*.ifo\0All Files\0*.*\0\0") ;
}
else
{
ofn.lpstrTitle = TEXT("Select Video file\0") ;
ofn.lpstrFilter = TEXT("AVI Files\0*.avi\0MPEG Files\0*.mpg\0All Files\0*.*\0\0") ;
}
ofn.nFilterIndex = 1 ;
ofn.lpstrFile = achFileName ;
ofn.nMaxFile = sizeof(achFileName) ;
ofn.lpstrFileTitle = NULL ;
ofn.nMaxFileTitle = 0 ;
ofn.lpstrInitialDir = NULL ;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY ;
if (GetOpenFileName(&ofn)) // user specified a file
{
if (! CreatePlayer(eType) || // creating player failed!!
NULL == gpPlayer ) // how!?!
{
DbgLog((LOG_ERROR, 0, TEXT("ERROR: Couldn't create %s player"),
DVD == eType ? "DVD" : "File")) ;
return FALSE ;
}
gpPlayer->SetFileName(achFileName) ;
return TRUE ; // user specified file name
}
// Either failed or user hit Esc.
DbgLog((LOG_TRACE, 3, TEXT("GetOpenFileName() cancelled/failed (Error %lu)"),
CommDlgExtendedError())) ;
return FALSE ; // DVD-Video volume not changed
}
BOOL IsVideoTypeKnown(void)
{
return (Unspecified != geVideoType) ;
}
VIDEO_TYPE GetVideoType(void)
{
return geVideoType ;
}
BOOL CreatePlayer(VIDEO_TYPE eType)
{
if (geVideoType == eType) // same type as before
{
if (gpPlayer) // we have already have the player
return TRUE ; // we'll use the same one; everything is OK
}
else // video type has changed
{
if (gpPlayer) // we created a player before...
{
delete gpPlayer ; // release it now
gpPlayer = NULL ;
}
}
// If we are here, we need to create a new player of the specified type
if (DVD == eType)
gpPlayer = new CDVDPlayer ;
else if (File == eType)
gpPlayer = new CFilePlayer ;
else // what then??
{
ASSERT(FALSE) ;
return NULL ;
}
geVideoType = eType ; // this our current video type
return TRUE ;
}
//
// OnEndOfPlayback(): Releases everything on end of playback (but checks to
// avoid doing it too many times) as it "may be" called a little more than
// we would like to.
//
void OnEndOfPlayback(HWND hWndApp)
{
DbgLog((LOG_TRACE, 5, TEXT("App's OnEndOfPlayback() entered"))) ;
if (0 != guTimerID) // if any timer is still set
{
BOOL bRes = KillTimer(hWndApp, TIMER_ID) ; // don't need that timer anymore
ASSERT(bRes) ; bRes = bRes; // Suppress C4189 warning
guTimerID = 0 ; // timer released
}
if (gpPlayer && gpPlayer->IsGraphReady())
{
DbgLog((LOG_TRACE, 5, TEXT("Turn off color keying before stopping the graph"))) ;
gpDDrawObj->SetOverlayState(FALSE) ; // don't paint color key in video's position
#ifndef NOFLIP
gpDDrawObj->UpdateAndFlipSurfaces() ; // flip the surface so that video doesn't show anymore
#endif // NOFLIP
gpPlayer->Stop() ;
// Remove the overlay callback interface for OverlayMixer
HRESULT hr = gpPlayer->SetOverlayCallback(NULL) ;
ASSERT(SUCCEEDED(hr)) ; hr = hr; // Suppress C4189 warning
gpPlayer->ClearGraph() ;
}
if (gpDDrawObj->IsInExclusiveMode())
{
gpDDrawObj->StopExclusiveMode(hWndApp) ;
// Resize main window to default size
SetWindowPos(ghWndApp, HWND_TOP, 0, 0, DEFAULT_WIDTH, DEFAULT_HEIGHT, 0);
}
}
//
// WndPorc(): Message handles for our sample app.
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HDC hDC ;
static PAINTSTRUCT ps ;
switch (message) {
case WM_ACTIVATEAPP:
//
// NOTE: We don't try to recover playback on switching back into focus.
//
gbAppActive = (BOOL) wParam ;
if (! gbAppActive ) // losing activation
{
DbgLog((LOG_TRACE, 2, TEXT("Got a WM_ACTIVATEAPP message with Active = %s"),
gbAppActive ? "TRUE" : "FALSE")) ;
OnEndOfPlayback(hWnd) ; // should stop playback now
}
break ;
case WM_TIMER:
DbgLog((LOG_TRACE, 4, TEXT("Got a WM_TIMER message with ID = %ld (Active = %s)"),
wParam, gbAppActive ? "T" : "F")) ;
if ( TIMER_ID != wParam || // this is not the timer we have set or
! gbAppActive || // the app isn't active anymore or
! gpPlayer->IsGraphReady() ) // the graph is not currently ready
// (...but we should have turned timer off then anyway!!)
break ; // don't do anything
//
// We could do some status update here that could be used by the
// UpdateAndFlipSurfaces() call below.
//
#ifndef NOFLIP
gpDDrawObj->UpdateAndFlipSurfaces() ;
#endif // NOFLIP
break;
case WM_COMMAND:
DbgLog((LOG_TRACE, 4, TEXT("Got a WM_COMMAND message with wParam = %ld"), wParam)) ;
MenuProc(hWnd, wParam, lParam) ;
break;
case WM_PLAY_EVENT:
DbgLog((LOG_TRACE, 4, TEXT("Got a WM_PLAY_EVENT message with wParam = %ld"), wParam)) ;
if (1 == OnPlaybackEvent(hWnd, wParam, lParam)) // playback ended
OnEndOfPlayback(hWnd) ; // do the necessary things
break ;
case WM_SIZE_CHANGE:
DbgLog((LOG_TRACE, 4, TEXT("Got a WM_SIZE_CHANGE message"))) ;
if (gpPlayer->IsGraphReady()) // ONLY if the graph is ready
SetVideoPosition(FALSE) ;
else
DbgLog((LOG_TRACE, 1, TEXT("WARNING: Got a WM_SIZE_CHANGE message after graph was released!!"))) ;
break ;
case WM_KEYUP:
DbgLog((LOG_TRACE, 4, TEXT("Got a WM_KEYUP message with wParam = %ld"), wParam)) ;
KeyProc(hWnd, wParam, lParam) ;
break ;
case WM_DESTROY:
OnEndOfPlayback(hWnd) ; // must stop playback before quitting
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hWnd, message, wParam, lParam));
}
return 0 ;
}
//
// KeyProc(): Handles key presses to exit playback (on Esc) or move the ball
// using arrow keys.
//
LRESULT CALLBACK KeyProc(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
DbgLog((LOG_TRACE, 5, TEXT("App's KeyProc() entered"))) ;
switch (wParam)
{
case VK_ESCAPE:
OnEndOfPlayback(hWnd) ;
break ;
case VK_UP:
gpDDrawObj->MoveBallPosition(0, -BALL_STEP) ;
break ;
case VK_DOWN:
gpDDrawObj->MoveBallPosition(0, BALL_STEP) ;
break ;
case VK_LEFT:
gpDDrawObj->MoveBallPosition(-BALL_STEP, 0) ;
break ;
case VK_RIGHT:
gpDDrawObj->MoveBallPosition(BALL_STEP, 0) ;
break ;
default:
break ;
}
return 0 ;
}
//
// About(): Dialog box code for the About box.
//
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
DbgLog((LOG_TRACE, 5, TEXT("App's About() entered"))) ;
switch (message) {
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, TRUE);
return TRUE;
}
break;
default:
break ;
}
return FALSE;
}
//
// OnPlaybackEvent(): Handles playback events, specially completed/stopped-on-error.
//
// Returns 0 if playback is continuing.
// Returns 1 if playback is over for any reason.
//
LRESULT OnPlaybackEvent(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
DbgLog((LOG_TRACE, 5,
TEXT("App's OnPlaybackEvent(0x%lx, 0x%lx) entered"),
wParam, lParam)) ;
IMediaEventEx *pME = (IMediaEventEx *) lParam ;
if (NULL == pME || Playing != gpPlayer->GetState())
{
DbgLog((LOG_TRACE, 1, TEXT("Either pME = NULL or not playing anymore. Skip everything."))) ;
return 0 ; // or 1 ??
}
LONG lEvent ;
LONG_PTR lParam1, lParam2 ;
//
// Because the message mode for IMediaEvent may not be set before
// we get the first event it's important to read all the events
// pending when we get a window message to say there are events pending.
// GetEvent() returns E_ABORT when no more event is left.
//
while (SUCCEEDED(pME->GetEvent(&lEvent, &lParam1, &lParam2, 0))) // no wait
{
switch (lEvent)
{
//
// First the DVD related events
//
case EC_DVD_STILL_ON:
DbgLog((LOG_TRACE, 5, TEXT("Playback Event: EC_DVD_STILL_ON"))) ;
break ;
case EC_DVD_STILL_OFF:
DbgLog((LOG_TRACE, 5, TEXT("Playback Event: EC_DVD_STILL_OFF"))) ;
break ;
case EC_DVD_DOMAIN_CHANGE:
DbgLog((LOG_TRACE, 5, TEXT("Playback Event: EC_DVD_DOMAIN_CHANGE, %ld"), lParam1)) ;
switch (lParam1)
{
case DVD_DOMAIN_FirstPlay: // = 1
case DVD_DOMAIN_Stop: // = 5
break ;
case DVD_DOMAIN_VideoManagerMenu: // = 2
case DVD_DOMAIN_VideoTitleSetMenu: // = 3
// Inform the app to update the menu option to show "Resume" now
break ;
case DVD_DOMAIN_Title: // = 4
// Inform the app to update the menu option to show "Menu" again
break ;
default: // hmmmm...
break ;
}
break ;
case EC_DVD_BUTTON_CHANGE:
DbgLog((LOG_TRACE, 5, TEXT("DVD Event: Button Changed to %d out of %d"),
lParam2, lParam1));
break;
case EC_DVD_TITLE_CHANGE:
DbgLog((LOG_TRACE, 5, TEXT("Playback Event: EC_DVD_TITLE_CHANGE"))) ;
break ;
case EC_DVD_CHAPTER_START:
DbgLog((LOG_TRACE, 5, TEXT("Playback Event: EC_DVD_CHAPTER_START"))) ;
break ;
case EC_DVD_CURRENT_TIME:
DbgLog((LOG_TRACE, 5, TEXT("Playback Event: EC_DVD_CURRENT_TIME"))) ;
break ;
//
// Then the general DirectShow related events
//
case EC_COMPLETE:
DbgLog((LOG_TRACE, 5, TEXT("Playback Event: Playback complete"))) ;
MessageBeep(MB_OK) ; // just to inform that the playback is over
// Remember to free the event params
pME->FreeEventParams(lEvent, lParam1, lParam2) ;
// We don't do the release part here. That will be done in WndProc()
// after return from this function.
return 1 ; // playback over
case EC_USERABORT:
case EC_ERRORABORT:
DbgLog((LOG_TRACE, 5, TEXT("Playback Event: 0x%lx"), lEvent)) ;
MessageBeep(MB_ICONEXCLAMATION) ; // to inform that the playback has errored out
// Remember to free the event params
pME->FreeEventParams(lEvent, lParam1, lParam2) ;
// We don't do the release part here. That will be done in WndProc()
// after return from this function.
return 1 ; // playback over
default:
DbgLog((LOG_TRACE, 5, TEXT("Ignored unknown playback event: 0x%lx"), lEvent)) ;
break ;
}
//
// Remember to free the event params
//
pME->FreeEventParams(lEvent, lParam1, lParam2) ;
} // end of while (GetEvent()) loop
return 0 ;
}
typedef enum _AM_TRANSFORM
{
AM_SHRINK,
AM_STRETCH
} AM_TRANSFORM ;
void TransformRect(RECT *prRect, double dPictAspectRatio, AM_TRANSFORM transform)
{
double dWidth, dHeight, dNewWidth, dNewHeight ;
double dResolutionRatio = 0.0, dTransformRatio = 0.0 ;
ASSERT(transform == AM_SHRINK || transform == AM_STRETCH) ;
dNewWidth = dWidth = prRect->right - prRect->left ;
dNewHeight = dHeight = prRect->bottom - prRect->top ;
dResolutionRatio = dWidth / dHeight ;
dTransformRatio = dPictAspectRatio / dResolutionRatio ;
// shrinks one dimension to maintain the coorect aspect ratio
if (transform == AM_SHRINK)
{
if (dTransformRatio > 1.0)
{
dNewHeight = dNewHeight / dTransformRatio ;
}
else if (dTransformRatio < 1.0)
{
dNewWidth = dNewWidth * dTransformRatio ;
}
}
// stretches one dimension to maintain the coorect aspect ratio
else if (transform == AM_STRETCH)
{
if (dTransformRatio > 1.0)
{
dNewWidth = dNewWidth * dTransformRatio ;
}
else if (dTransformRatio < 1.0)
{
dNewHeight = dNewHeight / dTransformRatio ;
}
}
if (transform == AM_SHRINK)
{
ASSERT(dNewHeight <= dHeight) ;
ASSERT(dNewWidth <= dWidth) ;
}
else
{
ASSERT(dNewHeight >= dHeight) ;
ASSERT(dNewWidth >= dWidth) ;
}
// cut or add equal portions to the changed dimension
prRect->left += (LONG)(dWidth - dNewWidth)/2 ;
prRect->right = prRect->left + (LONG)dNewWidth ;
prRect->top += (LONG)(dHeight - dNewHeight)/2 ;
prRect->bottom = prRect->top + (LONG)dNewHeight ;
}
//
// SetVideoPosition(): Gets the original video size and positions it at the center.
//
void SetVideoPosition(BOOL bSetBallPosition)
{
DbgLog((LOG_TRACE, 5, TEXT("App's SetVideoPosition() entered"))) ;
DWORD dwVideoWidth, dwVideoHeight ;
DWORD dwARX, dwARY ;
gpPlayer->GetNativeVideoData(&dwVideoWidth, &dwVideoHeight, &dwARX, &dwARY) ;
DbgLog((LOG_TRACE, 5, TEXT("Native video size: %lu x %lu, Aspect Ratio: %lu x %lu"),
dwVideoWidth, dwVideoHeight, dwARX, dwARY)) ;
// Update output size to make it aspect ratio corrected
RECT rectCorrected ;
SetRect(&rectCorrected, 0, 0, dwVideoWidth, dwVideoHeight) ;
TransformRect(&rectCorrected, (double)dwARX / (double)dwARY, AM_STRETCH) ;
DbgLog((LOG_TRACE, 5, TEXT("Updated video size: %ld x %ld"),
RECTWIDTH(rectCorrected), RECTHEIGHT(rectCorrected))) ;
RECT ScrnRect ;
gpDDrawObj->GetScreenRect(&ScrnRect) ;
DbgLog((LOG_TRACE, 5, TEXT("Screen size is %ld x %ld"),
RECTWIDTH(ScrnRect), RECTHEIGHT(ScrnRect))) ;
DWORD dwVideoTop ;
DWORD dwVideoLeft ;
if (RECTWIDTH(rectCorrected) <= RECTWIDTH(ScrnRect) && // video width less than screen
RECTHEIGHT(rectCorrected) <= RECTHEIGHT(ScrnRect)) // video height less than screen
{
dwVideoLeft = (RECTWIDTH(ScrnRect) - RECTWIDTH(rectCorrected)) / 2 ;
dwVideoTop = (RECTHEIGHT(ScrnRect) - RECTHEIGHT(rectCorrected)) / 2 ;
}
else // video width more than screen
{
rectCorrected = ScrnRect ;
TransformRect(&rectCorrected, (double)dwARX / (double)dwARY, AM_SHRINK) ;
dwVideoLeft = rectCorrected.left ;
dwVideoTop = rectCorrected.top ;
}
gpDDrawObj->SetVideoPosition(dwVideoLeft, dwVideoTop,
RECTWIDTH(rectCorrected), RECTHEIGHT(rectCorrected)) ;
if (bSetBallPosition) // if ball position should be (re)set
gpDDrawObj->SetBallPosition(dwVideoLeft, dwVideoTop,
RECTWIDTH(rectCorrected), RECTHEIGHT(rectCorrected)) ;
else // don't reset the ball position, just...
gpDDrawObj->MoveBallPosition(0, 0) ; // ... make sure it's in the new video area
gpPlayer->SetVideoPosition(dwVideoLeft, dwVideoTop,
RECTWIDTH(rectCorrected), RECTHEIGHT(rectCorrected)) ;
DbgLog((LOG_TRACE, 5, TEXT("Video is %ld x %ld at (%ld x %ld)"),
RECTWIDTH(rectCorrected), RECTHEIGHT(rectCorrected), dwVideoLeft, dwVideoTop)) ;
}
//
// StartPlay(): Switches to fulscreen exclusive mode, sets up for selected media
// playback, gets the video size and positions video at the center, starts playing
// and sets a timer to tell WndProc() every 1/10 second.
//
LRESULT StartPlay(HWND hWndApp)
{
HRESULT hr ;
DbgLog((LOG_TRACE, 5, TEXT("App's StartPlay() entered"))) ;
if (! IsVideoTypeKnown() )
{
MessageBox(hWndApp,
TEXT("No playback option (DVD/File) has been specified through the menu option yet.\nCan't run test."),
TEXT("Sorry"), MB_OK | MB_ICONINFORMATION) ;
return 0 ;
}
//
// Make sure that DShow components are installed etc so that
// the graph building can be init-ed
//
if (! gpPlayer->Initialize() )
{
MessageBox(hWndApp,
TEXT("DShow components couldn't be initialized.\n\nCan't run test.\nPlease check DxMedia installation"),
TEXT("Sorry"), MB_OK | MB_ICONSTOP) ;
return 0 ;
}
//
// Go into fullscreen exclusive mode
//
hr = gpDDrawObj->StartExclusiveMode(hWndApp) ;
if (FAILED(hr)) // error message shown by the above method
{
gpPlayer->ClearGraph() ;
return 0 ;
}
//
// Build video playback graph
//
hr = gpPlayer->BuildGraph(hWndApp, gpDDrawObj->GetDDObject(), gpDDrawObj->GetDDPrimary()) ;
if (FAILED(hr))
{
gpPlayer->ClearGraph() ;
gpDDrawObj->StopExclusiveMode(hWndApp) ; // get out of exclusive mode
return 0 ;
}
//
// Specify the overlay callback interface for OverlayMixer to notify us
//
hr = gpPlayer->SetOverlayCallback(gpDDrawObj->GetCallbackInterface()) ;
ASSERT(SUCCEEDED(hr)) ;
//
// Pause the video playback graph to get it ready to play
//
BOOL bSuccess = gpPlayer->Pause() ;
if (!bSuccess)
{
gpPlayer->SetOverlayCallback(NULL) ; // first remove overlay callback
gpPlayer->ClearGraph() ; // then remove graph
gpDDrawObj->StopExclusiveMode(hWndApp) ; // then get out of exclusive mode
return 0 ;
}
//
// Get the color key info from the Player object and pass it to the DDraw object
//
DWORD dwVideoColorKey ;
gpPlayer->GetColorKey(&dwVideoColorKey) ;
gpDDrawObj->SetColorKey(dwVideoColorKey) ;
//
// Get the video width and height, center it and pass the coordinates to
// the player and the DDraw object
//
SetVideoPosition(TRUE) ;
//
// Create the first screen on back buffer and then flip
//
#ifndef NOFLIP
gpDDrawObj->UpdateAndFlipSurfaces() ;
#endif // NOFLIP
//
// Play video now...
//
if (! gpPlayer->Play() )
{
gpPlayer->SetOverlayCallback(NULL) ; // first remove overlay callback
gpPlayer->ClearGraph() ; // then remove graph
gpDDrawObj->StopExclusiveMode(hWndApp) ; // then get out of exclusive mode
return 0 ;
}
//
// Now set a timer based on which we'll update the buffers and flip
//
guTimerID = (UINT) SetTimer(hWndApp, TIMER_ID, TIMER_RATE, NULL) ;
ASSERT(0 != guTimerID) ;
// We are done with starting the playback. WndProc will stop the playback on
// playback event messages or user hitting Esc key as well the timer based
// actions will be taken in WM_TIMER handler there.
return 1 ;
}

View File

@@ -0,0 +1,5 @@
; Module-Definition file for DDrawXCL Sample -- used by LINK.EXE
; ==========================================================================
; This isn't really needed for an Application, but it's handy to use for
; setting the 'NAME DDrawXCL ; application's module name

View File

@@ -0,0 +1,133 @@
# Microsoft Developer Studio Project File - Name="ddrawxcl" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Application" 0x0101
CFG=ddrawxcl - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "ddrawxcl.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "ddrawxcl.mak" CFG="ddrawxcl - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "ddrawxcl - Win32 Release" (based on "Win32 (x86) Application")
!MESSAGE "ddrawxcl - Win32 Debug" (based on "Win32 (x86) Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "ddrawxcl - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /I "..\..\BaseClasses" /I "..\..\..\..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
# SUBTRACT CPP /YX
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG" /d "WIN32"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
# ADD LINK32 ..\..\baseclasses\release\strmbase.lib quartz.lib kernel32.lib user32.lib comdlg32.lib ole32.lib oleaut32.lib gdi32.lib ddraw.lib msvcrt.lib uuid.lib advapi32.lib winmm.lib /nologo /stack:0x200000,0x200000 /subsystem:windows /pdb:none /machine:I386 /nodefaultlib
!ELSEIF "$(CFG)" == "ddrawxcl - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /Zi /Od /I "..\..\BaseClasses" /I "..\..\..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "DEBUG" /FD /c
# SUBTRACT CPP /YX
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG" /d "WIN32"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
# ADD LINK32 ..\..\baseclasses\debug\strmbasd.lib quartz.lib kernel32.lib user32.lib comdlg32.lib ole32.lib oleaut32.lib gdi32.lib ddraw.lib msvcrtd.lib uuid.lib advapi32.lib winmm.lib /nologo /stack:0x200000,0x200000 /subsystem:windows /pdb:none /debug /machine:I386 /nodefaultlib
!ENDIF
# Begin Target
# Name "ddrawxcl - Win32 Release"
# Name "ddrawxcl - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "*.cpp;*.rc;*.ico"
# Begin Source File
SOURCE=.\ddrawobj.cpp
# End Source File
# Begin Source File
SOURCE=.\ddrawxcl.cpp
# End Source File
# Begin Source File
SOURCE=.\ddrawxcl.ico
# End Source File
# Begin Source File
SOURCE=.\ddrawxcl.rc
# End Source File
# Begin Source File
SOURCE=.\vidplay.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "*.h"
# Begin Source File
SOURCE=.\ddrawobj.h
# End Source File
# Begin Source File
SOURCE=.\ddrawxcl.h
# End Source File
# Begin Source File
SOURCE=.\vidplay.h
# End Source File
# End Group
# End Target
# End Project

View File

@@ -0,0 +1,29 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "ddrawxcl"=.\ddrawxcl.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

View File

@@ -0,0 +1,110 @@
//------------------------------------------------------------------------------
// File: DDrawXcl.h
//
// Desc: DirectShow sample code - DDraw Exclusive Mode Video Playback
// test/sample application header file.
//
// Copyright (c) 1993-2001 Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------
//
// App menu ids
//
#define IDM_SELECTDVD 101
#define IDM_SELECTFILE 102
#define IDM_ABOUT 103
#define IDM_EXIT 104
#define IDM_STARTPLAY 111
#define IDC_STATIC -1
//
// Version info related constant ids
//
#define DLG_VERFIRST 400
#define IDC_COMPANY DLG_VERFIRST
#define IDC_FILEDESC DLG_VERFIRST+1
#define IDC_PRODVER DLG_VERFIRST+2
#define IDC_COPYRIGHT DLG_VERFIRST+3
#define IDC_OSVERSION DLG_VERFIRST+4
#define IDC_TRADEMARK DLG_VERFIRST+5
#define DLG_VERLAST DLG_VERFIRST+5
#define IDC_LABEL DLG_VERLAST+1
//
// Message displayed on failure to start playback
//
#define STR_EXCLUSIVE_MODE_FAILURE \
TEXT("Exclusive mode playback failed to start.") \
TEXT("\nPlease verify that the selected file can be played with your video card.") \
TEXT("\n\nMore information:") \
TEXT("\n----------------------") \
TEXT("\nSome display cards do not support RGB overlays in hardware, but the decoder\n") \
TEXT("used by the selected media file may require them. If the filter upstream\n") \
TEXT("of the overlay mixer proposes only RGB formats, and the video card does not\n") \
TEXT("support RGB overlays in hardware, then the filter graph manager will not\n") \
TEXT("be able to connect the filters to complete the graph.")
//
// App string resource ids
//
#define IDS_APP_TITLE 500
#define IDS_APP_NAME 501
#define IDS_WINDOW_TITLE 502
#define IDS_VER_INFO_LANG 503
#define IDS_VERSION_ERROR 504
//
// Some constants
//
#define TIMER_ID 1
#define TIMER_RATE 100
//
// Some enumerated types
//
typedef enum {
Unspecified = 0, DVD , File
} VIDEO_TYPE ;
//
// Function signatures for Windows
//
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow) ;
BOOL InitApplication(void) ;
BOOL InitInstance(int nCmdShow) ;
LRESULT CALLBACK MenuProc(HWND hWnd, WPARAM wParam, LPARAM lParam) ;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) ;
LRESULT CALLBACK KeyProc(HWND hWnd, WPARAM wParam, LPARAM lParam) ;
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) ;
LRESULT StartPlay(HWND hWndApp) ;
LRESULT OnPlaybackEvent(HWND hWnd, WPARAM wParam, LPARAM lParam) ;
void OnEndOfPlayback(HWND hWnd) ;
void SetVideoPosition(BOOL bSetBallPosition) ;
BOOL FileSelect(HWND hWnd, VIDEO_TYPE eType) ;
BOOL CreatePlayer(VIDEO_TYPE eType) ;
BOOL IsVideoTypeKnown(void) ;
VIDEO_TYPE GetVideoType(void) ;
//
// Global variables used by the (Windows) app
//
HWND ghWndApp ;
TCHAR gszAppName[10] ;
TCHAR gszAppTitle[100] ;
TCHAR gszDirection[100] ;
HINSTANCE ghInstance ;
CBaseVideoPlayer *gpPlayer ;
CDDrawObject *gpDDrawObj ;
UINT guTimerID ;
VIDEO_TYPE geVideoType ;
BOOL gbAppActive ;

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

View File

@@ -0,0 +1,217 @@
# Microsoft Developer Studio Generated NMAKE File, Based on ddrawxcl.dsp
!IF "$(CFG)" == ""
CFG=ddrawxcl - Win32 Debug
!MESSAGE No configuration specified. Defaulting to ddrawxcl - Win32 Debug.
!ENDIF
!IF "$(CFG)" != "ddrawxcl - Win32 Release" && "$(CFG)" != "ddrawxcl - Win32 Debug"
!MESSAGE Invalid configuration "$(CFG)" specified.
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "ddrawxcl.mak" CFG="ddrawxcl - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "ddrawxcl - Win32 Release" (based on "Win32 (x86) Application")
!MESSAGE "ddrawxcl - Win32 Debug" (based on "Win32 (x86) Application")
!MESSAGE
!ERROR An invalid configuration is specified.
!ENDIF
!IF "$(OS)" == "Windows_NT"
NULL=
!ELSE
NULL=nul
!ENDIF
!IF "$(CFG)" == "ddrawxcl - Win32 Release"
OUTDIR=.\Release
INTDIR=.\Release
# Begin Custom Macros
OutDir=.\Release
# End Custom Macros
ALL : "$(OUTDIR)\ddrawxcl.exe"
CLEAN :
-@erase "$(INTDIR)\ddrawobj.obj"
-@erase "$(INTDIR)\ddrawxcl.obj"
-@erase "$(INTDIR)\ddrawxcl.res"
-@erase "$(INTDIR)\vc60.idb"
-@erase "$(INTDIR)\vidplay.obj"
-@erase "$(OUTDIR)\ddrawxcl.exe"
"$(OUTDIR)" :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
CPP=cl.exe
CPP_PROJ=/nologo /ML /W3 /GX /O2 /I "..\..\BaseClasses" /I "..\..\..\..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
.c{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cpp{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cxx{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.c{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cpp{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cxx{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
MTL=midl.exe
MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
RSC=rc.exe
RSC_PROJ=/l 0x409 /fo"$(INTDIR)\ddrawxcl.res" /d "NDEBUG"
BSC32=bscmake.exe
BSC32_FLAGS=/nologo /o"$(OUTDIR)\ddrawxcl.bsc"
BSC32_SBRS= \
LINK32=link.exe
LINK32_FLAGS=..\..\baseclasses\release\strmbase.lib quartz.lib kernel32.lib user32.lib comdlg32.lib ole32.lib oleaut32.lib gdi32.lib ddraw.lib msvcrt.lib uuid.lib advapi32.lib winmm.lib /nologo /subsystem:windows /pdb:none /machine:I386 /nodefaultlib /out:"$(OUTDIR)\ddrawxcl.exe" /stack:0x200000,0x200000
LINK32_OBJS= \
"$(INTDIR)\ddrawobj.obj" \
"$(INTDIR)\ddrawxcl.obj" \
"$(INTDIR)\vidplay.obj" \
"$(INTDIR)\ddrawxcl.res"
"$(OUTDIR)\ddrawxcl.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
$(LINK32) @<<
$(LINK32_FLAGS) $(LINK32_OBJS)
<<
!ELSEIF "$(CFG)" == "ddrawxcl - Win32 Debug"
OUTDIR=.\Debug
INTDIR=.\Debug
# Begin Custom Macros
OutDir=.\Debug
# End Custom Macros
ALL : "$(OUTDIR)\ddrawxcl.exe"
CLEAN :
-@erase "$(INTDIR)\ddrawobj.obj"
-@erase "$(INTDIR)\ddrawxcl.obj"
-@erase "$(INTDIR)\ddrawxcl.res"
-@erase "$(INTDIR)\vc60.idb"
-@erase "$(INTDIR)\vc60.pdb"
-@erase "$(INTDIR)\vidplay.obj"
-@erase "$(OUTDIR)\ddrawxcl.exe"
"$(OUTDIR)" :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
CPP=cl.exe
CPP_PROJ=/nologo /MLd /W3 /GX /Zi /Od /I "..\..\BaseClasses" /I "..\..\..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "DEBUG" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
.c{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cpp{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cxx{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.c{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cpp{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cxx{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
MTL=midl.exe
MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
RSC=rc.exe
RSC_PROJ=/l 0x409 /fo"$(INTDIR)\ddrawxcl.res" /d "_DEBUG"
BSC32=bscmake.exe
BSC32_FLAGS=/nologo /o"$(OUTDIR)\ddrawxcl.bsc"
BSC32_SBRS= \
LINK32=link.exe
LINK32_FLAGS=..\..\baseclasses\debug\strmbasd.lib quartz.lib kernel32.lib user32.lib comdlg32.lib ole32.lib oleaut32.lib gdi32.lib ddraw.lib msvcrtd.lib uuid.lib advapi32.lib winmm.lib /nologo /subsystem:windows /pdb:none /debug /machine:I386 /nodefaultlib /out:"$(OUTDIR)\ddrawxcl.exe" /stack:0x200000,0x200000
LINK32_OBJS= \
"$(INTDIR)\ddrawobj.obj" \
"$(INTDIR)\ddrawxcl.obj" \
"$(INTDIR)\vidplay.obj" \
"$(INTDIR)\ddrawxcl.res"
"$(OUTDIR)\ddrawxcl.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
$(LINK32) @<<
$(LINK32_FLAGS) $(LINK32_OBJS)
<<
!ENDIF
!IF "$(NO_EXTERNAL_DEPS)" != "1"
!IF EXISTS("ddrawxcl.dep")
!INCLUDE "ddrawxcl.dep"
!ELSE
!MESSAGE Warning: cannot find "ddrawxcl.dep"
!ENDIF
!ENDIF
!IF "$(CFG)" == "ddrawxcl - Win32 Release" || "$(CFG)" == "ddrawxcl - Win32 Debug"
SOURCE=.\ddrawobj.cpp
"$(INTDIR)\ddrawobj.obj" : $(SOURCE) "$(INTDIR)"
SOURCE=.\ddrawxcl.cpp
"$(INTDIR)\ddrawxcl.obj" : $(SOURCE) "$(INTDIR)"
SOURCE=.\ddrawxcl.rc
"$(INTDIR)\ddrawxcl.res" : $(SOURCE) "$(INTDIR)"
$(RSC) $(RSC_PROJ) $(SOURCE)
SOURCE=.\vidplay.cpp
"$(INTDIR)\vidplay.obj" : $(SOURCE) "$(INTDIR)"
!ENDIF

View File

@@ -0,0 +1,219 @@
//Microsoft Developer Studio generated resource script.
//
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#define APSTUDIO_HIDDEN_SYMBOLS
#include "windows.h"
#undef APSTUDIO_HIDDEN_SYMBOLS
#include "ddrawxcl.h"
#include "winver.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
DDRAWXCL ICON DISCARDABLE "DDrawXcl.ICO"
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//
DDRAWXCL MENU DISCARDABLE
BEGIN
POPUP "&File"
BEGIN
MENUITEM "Select &DVD...", IDM_SELECTDVD
MENUITEM "Select &File...", IDM_SELECTFILE
MENUITEM SEPARATOR
MENUITEM "&Play", IDM_STARTPLAY
MENUITEM SEPARATOR
MENUITEM "&About...", IDM_ABOUT
MENUITEM SEPARATOR
MENUITEM "E&xit", IDM_EXIT
END
END
/////////////////////////////////////////////////////////////////////////////
//
// Accelerator
//
DDRAWXCL ACCELERATORS MOVEABLE PURE
BEGIN
"?", IDM_ABOUT, ASCII, ALT
"/", IDM_ABOUT, ASCII, ALT
END
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
ABOUTBOX DIALOG DISCARDABLE 20, 20, 180, 94
STYLE DS_MODALFRAME | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "About DDrawXCL Sample"
FONT 8, "MS Shell Dlg"
BEGIN
ICON "DDrawXcl",IDC_STATIC,19,7,21,20
CTEXT "DDraw Exclusive Mode Video Playback Sample",IDC_STATIC,
6,32,167,8
CTEXT "Version 8.10",IDC_STATIC,6,42,167,8
CTEXT "Copyright <20> 1998-2001 Microsoft Corporation",IDC_STATIC,
6,53,167,8
DEFPUSHBUTTON "OK",IDOK,73,70,32,14,WS_GROUP
CTEXT "DDrawXCL Sample",IDC_STATIC,51,12,76,11
END
#ifndef _MAC
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
1 VERSIONINFO
FILEVERSION 8,1,0,0
PRODUCTVERSION 8,1,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0xbL
#else
FILEFLAGS 0xaL
#endif
FILEOS 0x4L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904e4"
BEGIN
VALUE "Comments", "DirectShow Sample\0"
VALUE "CompanyName", "Microsoft\0"
VALUE "FileDescription", "DDraw Exclusive Mode Video Playback Sample\0"
VALUE "FileVersion", "8.10\0"
VALUE "InternalName", "DDrawXcl\0"
VALUE "LegalCopyright", "Copyright (C) 1998-2001 Microsoft Corporation\0"
VALUE "LegalTrademarks", "Microsoft(R) is a registered trademark of Microsoft Corporation. Windows(TM) is a trademark of Microsoft Corporation\0"
VALUE "OriginalFilename", "DDrawXCL.EXE\0"
VALUE "PrivateBuild", "\0"
VALUE "ProductName", "DirectX 8 SDK\0"
VALUE "ProductVersion", "8.1\0"
VALUE "SpecialBuild", "\0"
END
BLOCK "041104e4"
BEGIN
VALUE "Comments", "DirectShow Sample\0"
VALUE "CompanyName", "Microsoft\0"
VALUE "FileDescription", "DDraw Exclusive Mode Video Playback Sample\0"
VALUE "FileVersion", "8.10\0"
VALUE "InternalName", "DDrawXcl\0"
VALUE "LegalCopyright", "Copyright (C) 1998-2001 Microsoft Corporation\0"
VALUE "LegalTrademarks", "Microsoft(R) is a registered trademark of Microsoft Corporation. Windows(TM) is a trademark of Microsoft Corporation\0"
VALUE "OriginalFilename", "DDrawXCL.EXE\0"
VALUE "PrivateBuild", "\0"
VALUE "ProductName", "DirectX 8 SDK\0"
VALUE "ProductVersion", "8.1\0"
VALUE "SpecialBuild", "\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1252, 0x411, 1252
END
END
#endif // !_MAC
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE
BEGIN
"#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
"#include ""windows.h""\r\n"
"#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
"#include ""ddrawxcl.h""\r\n"
"#include ""winver.h""\r\n"
"\0"
END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO DISCARDABLE
BEGIN
"ABOUTBOX", DIALOG
BEGIN
BOTTOMMARGIN, 70
END
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE DISCARDABLE
BEGIN
500 "DDraw Exclusive Mode Video Playback Sample"
IDS_APP_NAME "DDrawXcl"
IDS_WINDOW_TITLE "DDrawXCL Player"
IDS_VER_INFO_LANG "\\StringFileInfo\\040904E4\\"
IDS_VERSION_ERROR "Error %lu"
END
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@@ -0,0 +1,159 @@
DirectShow Sample -- DDrawXCL
-----------------------------
DirectDraw Exclusive Mode Video Playback Capability
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
General Information:
====================
Now video can be played back from AVI, MPEG files as well as DVD titles
even in DirectDraw exclusive fullscreen mode. This is expected to be
very helpful to games and interactive content development.
The DirectX SDK includes various components that together
offer this capability. An updated Overlay Mixer filter in DirectShow
is now capable of using a DirectDraw object and primary surface provided
by an application, rather than insisting on using its own.
A new COM interface, IDDrawExclModeVideo, has been added on the Overlay
Mixer filter which allows applications to specify DirectDraw parameters
and playback position, size, etc. An app can do QueryInterface() on the
Overlay Mixer filter to get the interface. This interface is fully
documented in the SDK help documentation.
Also another new COM interface, IDDrawExclModeVideoCallback, has been
defined in the SDK. An application should implement an object that supports
this interface to have a notification set up with the OverlayMixer about
any changes to the overlay size, position, color key, etc. This callback
mechanism allows any color key flashes and/or strips to be avoided.
We have also updated the DVD graph builder object and some methods of the
IDvdGraphBuilder interface which allows applications to use the updated
DVD graph builder object to pass the DirectDraw-related information to the
Overlay Mixer for use in DVD playback filter graph building operation.
Using a couple of other methods available on the IDDrawExclModeVideo
interface, applications can get the color key information for
superimposing graphics on top of video playing in the background. All of
these changes have been fully documented in the SDK help.
A sample application, DDrawXcl, has also been added to the SDK samples.
This application consists of:
* A DirectDraw object (DDrawObj.h, .cpp) that wraps all DirectDraw
functionality using IDirectDraw* COM interfaces as well as the
IDDrawExclModeVideo interface.
* A video playback object (VidPlay.h, .cpp) that implements the details
of building a filter graph to play AVI/MPEG files as well as DVD titles.
* An overlay notification sink object that receives the overlay change
related callbacks from OverlayMixer and takes appropriate actions.
* A Windows application that uses the above objects to:
- Go into fullscreen exclusive mode, switch to 800x600x8 (we just chose
one particular mode), and create a primary surface with one back buffer.
- Build a filter graph to playback the selected type of video using
the DirectDraw object and surface provided by the application,
starts playing it and sets a timer to fire every 0.1 second.
- On the timer event, the application draws color key of the required
dimension on the back buffer, draws a ball that can be moved using
keystrokes, draws an updated number of flips completed, and flips the
surfaces.
- The callback notification object informs the DDraw object when color
keying of the video area should be started/stopped.
This is one of the basic requirements for games and interactive
content to play video using DirectShow inside the application.
The Limitations/Rules:
======================
1. The sequence of calls to get the application-created DirectDraw parameters
to be used by OverlayMixer is as follows --
For DVD:
- create the DVD graph builder object
- call IDvdGraphBuilder::GetDvdInterface() for IDDrawExclModeVideo
interface. This returns the IDDrawExclModeVideo interface of the
OverlayMixer in the DVD playback filter graph.
- call IDDrawExclModeVideo::SetDDrawObject() to set the DDraw object
- call IDDrawExclModeVideo::SetDDrawSurface() to set the DDraw surface
- call IDvdGraphBuilder::RenderDvdVideoVolume() to build a DVD graph
- call IDvdGraphBuilder::GetDvdInterface() to get a IMixerPinConfig(2)
interface pointer to the FIRST (only) input pin of the OverlayMixer.
- get color key info using IMixerPinConfig(2)::GetColorKey()
method. Also set the aspect ratio mode to stretching from the
default letter box mode of the OverlayMixer.
- call IDDrawExclModeVideo::SetCallbackInterface() with the pointer to the
object implementing the IDDrawExclModeVideoCallback interface.
- get the native video size and aspect ratio through
IDDrawExclModeVideo::GetNativeVideoProps() method, transform the width
and height based on the retrieved aspect ratio, and set the final video
size and position using IDDrawExclModeVideo::SetDDrawParameters() method.
For AVI/MPEG:
- create an empty filter graph
- call IGraphBuilder::RenderFile() on the specified file to build graph.
- instantiate the OverlayMixer filter and add it to the graph.
- call IDDrawExclModeVideo::SetDDrawObject()
- call IDDrawExclModeVideo::SetDDrawSurface()
- connect the decoded video to the Overlay Mixer's first input pin
- remove the Video Renderer filter as it's a windowless playback case.
- get IMixerPinConfig(2) interface from the first input pin of the
OverlayMixer to get the color key through GetColorKey() method.
Also set the aspect ratio mode to stretching from the default letter box
mode of the OverlayMixer.
- call IDDrawExclModeVideo::SetCallbackInterface() with the pointer to the
object implementing the IDDrawExclModeVideoCallback interface.
- get the native video size and aspect ratio through
IDDrawExclModeVideo::GetNativeVideoProps() method, transform the width
and height based on the retrieved aspect ratio, and set the final video
size and position using IDDrawExclModeVideo::SetDDrawParameters() method.
2. The object implementing IDDrawExclModeVideoCallback interface has been
kept very simple. It stops color keying of the video area on the back buffer
when it gets the OnUpdateOverlay() call with input parameter bBefore=TRUE.
The color keying is turned on again on getting another OnUpdateOverlay() call
with bBefore=FALSE and with the dwFlags indicating that the overlay is visible.
3. The SetDDraw*() methods can be called only when the pins of the Overlay
Mixer are not connected. Otherwise, the calls will fail.
4. The application has to draw colorkey at the right position on the (back
buffer of the) primary surface to get the video to appear. In the exclusive
mode, the Overlay Mixer doesn't draw color key at all.
5. For DVDs, the subpicture and line21 (closed caption) data are intentionally
not rendered in the exclusive mode. The DVD graph builder will not return
S_FALSE for this only.
Known Issues:
=============
1. The ball drawn on top of the video only moves when an arrow key is
pressed AND released. Holding the arrow key down doesn't move the ball.
This was a conscious decision made for the sample application.
2. The application stops playing the video and tears down the filter graph
when it switches to non exclusive mode on getting an Alt-Tab keystroke. The
playback is not resumed on activating the application.
3. The application fills the whole back buffer with black color and then
Blts the color key to the target video rectangle. This is not required unless
the video is continually changing position. For video playing at the same
position, just erasing the previous position of the ball with color key
should be sufficient. The comment at the top of the CDDrawObject::FillSurface()
method should hopefully not cause any confusion.
4. Some AVI files (MS-CRAM, Duck compressed) fail to connect to the
OverlayMixer filter on some display cards. This causes the sample app to
fail in building the graph. As a result, such files cannot be played back on
some systems.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,142 @@
//------------------------------------------------------------------------------
// File: VidPlay.h
//
// Desc: DirectShow sample code - video (DVD and file) playback
// class header file.
//
// Copyright (c) 1993-2001 Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------
// Suppress C4127: conditional expression is constant
#pragma warning(disable:4127)
//
// Some enumerated type definitions...
//
// Player state
typedef enum {
Uninitialized = 0, Stopped, Paused, Playing, Scanning
} PLAYER_STATE ;
// Define a special WM message for playback related events from DShow filtergraph
#define WM_PLAY_EVENT WM_USER + 100
#define WM_SIZE_CHANGE WM_USER + 101
#define DEFAULT_WIDTH 400
#define DEFAULT_HEIGHT 240
//
// Video Playback base class
//
class CBaseVideoPlayer
{
public: // public methods for Windows structure to call
CBaseVideoPlayer(void) ;
~CBaseVideoPlayer(void) ;
virtual BOOL Initialize(void) = 0 ;
virtual HRESULT BuildGraph(HWND hWndApp, LPDIRECTDRAW pDDObj,
LPDIRECTDRAWSURFACE pDDPrimary) = 0 ;
virtual HRESULT ClearGraph(void) = 0 ;
virtual HRESULT GetNativeVideoData(DWORD *pdwWidth, DWORD *pdwHeight, DWORD *pdwARX, DWORD *pdwARY) = 0 ;
virtual HRESULT SetVideoPosition(DWORD dwLeft, DWORD dwTop, DWORD dwWidth, DWORD dwHeight) = 0 ;
virtual HRESULT GetInterfaces(HWND hWndApp) ;
virtual HRESULT SetOverlayCallback(IDDrawExclModeVideoCallback *pCallback) = 0 ;
HRESULT GetColorKey(DWORD *pdwColorKey) ;
BOOL Play(void) ;
BOOL Pause(void) ;
BOOL Stop(void) ;
inline void SetFileName(LPCTSTR lpszFileName) { lstrcpy(m_achFileName, lpszFileName) ; } ;
inline BOOL IsGraphReady(void) { return (Uninitialized != m_eState) ; } ;
inline PLAYER_STATE GetState(void) { return m_eState ; } ;
inline void SetColorKey(DWORD dwColorKey) { m_dwColorKey = dwColorKey ; } ;
inline LPCTSTR GetFileName(void) { return m_achFileName ; } ;
protected:
virtual void ReleaseInterfaces(void) ;
virtual HRESULT GetColorKeyInternal(IBaseFilter *pOvM = NULL) = 0 ;
private:
void WaitForState(FILTER_STATE State) ;
protected: // semi-internal state info (to be shared with derived classes)
IGraphBuilder *m_pGraph ; // IGraphBuilder interface
private: // internal state info
PLAYER_STATE m_eState ; // player state (run/pause/stop/...)
TCHAR m_achFileName[MAX_PATH] ; // current file name
IMediaControl *m_pMC ; // IMediaControl interface
IMediaEventEx *m_pME ; // IMediaEventEx interface
DWORD m_dwColorKey ; // color key to be used for video
} ;
//
// DVD Playback class
//
class CDVDPlayer : public CBaseVideoPlayer
{
public: // public methods for Windows structure to call
CDVDPlayer(void) ;
~CDVDPlayer(void) ;
BOOL Initialize(void) ;
HRESULT BuildGraph(HWND hWndApp, LPDIRECTDRAW pDDObj, LPDIRECTDRAWSURFACE pDDPrimary) ;
HRESULT ClearGraph(void) ;
HRESULT GetNativeVideoData(DWORD *pdwWidth, DWORD *pdwHeight, DWORD *pdwARX, DWORD *pdwARY) ;
HRESULT SetVideoPosition(DWORD dwLeft, DWORD dwTop, DWORD dwWidth, DWORD dwHeight) ;
HRESULT GetInterfaces(HWND hWndApp) ;
HRESULT SetOverlayCallback(IDDrawExclModeVideoCallback *pCallback) ;
private: // private helper methods for the class' own use
void ReleaseInterfaces(void) ;
HRESULT GetColorKeyInternal(IBaseFilter *pOvM = NULL) ;
DWORD GetStatusText(AM_DVD_RENDERSTATUS *pStatus,
LPTSTR lpszStatusText,
DWORD dwMaxText) ;
private: // internal state info
IDvdGraphBuilder *m_pDvdGB ; // IDvdGraphBuilder interface
IDvdInfo2 *m_pDvdI ; // IDvdInfo interface
IDvdControl2 *m_pDvdC ; // IDvdControl interface
} ;
//
// File Playback class
//
class CFilePlayer : public CBaseVideoPlayer
{
public: // public methods for Windows structure to call
CFilePlayer(void) ;
~CFilePlayer(void) ;
BOOL Initialize(void) ;
HRESULT BuildGraph(HWND hWndApp, LPDIRECTDRAW pDDObj, LPDIRECTDRAWSURFACE pDDPrimary) ;
HRESULT ClearGraph(void) ;
HRESULT GetNativeVideoData(DWORD *pdwWidth, DWORD *pdwHeight, DWORD *pdwARX, DWORD *pdwARY) ;
HRESULT SetVideoPosition(DWORD dwLeft, DWORD dwTop, DWORD dwWidth, DWORD dwHeight) ;
HRESULT GetInterfaces(HWND hWndApp) ;
HRESULT SetOverlayCallback(IDDrawExclModeVideoCallback *pCallback) ;
private: // private helper methods for the class' own use
void ReleaseInterfaces() ;
HRESULT GetColorKeyInternal(IBaseFilter *pOvM = NULL) ;
BOOL IsOvMConnected(IBaseFilter *pOvM) ;
HRESULT GetVideoRendererInterface(IBaseFilter **ppVR) ;
HRESULT AddOvMToGraph(IBaseFilter **ppOvM, LPDIRECTDRAW pDDObj,
LPDIRECTDRAWSURFACE pDDPrimary) ;
HRESULT SetDDrawParams(IBaseFilter *pOvM, LPDIRECTDRAW pDDObj,
LPDIRECTDRAWSURFACE pDDPrimary) ;
HRESULT PutVideoThroughOvM(IBaseFilter *pOvM, IBaseFilter *pVR) ;
private: // internal state info
IDDrawExclModeVideo *m_pDDXM ; // IDDrawExclModeVideo interface
} ;