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:
@@ -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 ;
|
||||
}
|
||||
@@ -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 ;
|
||||
} ;
|
||||
@@ -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 ;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
@@ -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 |
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
} ;
|
||||
Reference in New Issue
Block a user