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,940 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File: DvdSample.cpp
|
||||
//
|
||||
// Desc: DVD Playback sample app using IDvdGraphBuilder,
|
||||
// IDvdInfo2, and IDvdControl2 interfaces.
|
||||
//
|
||||
// This contains all Windows-related "plumbing" for the application
|
||||
//
|
||||
// Copyright (c) 1999-2001 Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#include <windows.h>
|
||||
#include <commdlg.h>
|
||||
#include <commctrl.h>
|
||||
|
||||
#include <dshow.h>
|
||||
#include "resource.h"
|
||||
|
||||
#include "DvdCore.h"
|
||||
#include "Dialogs.h"
|
||||
#include "DvdSample.h"
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Global data
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const PTSTR APPNAME = TEXT("DVDSample");
|
||||
CApp g_App;
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Type Definitions
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
typedef UINT (CALLBACK* PFNDLL_STES)(UINT);
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Name: WinMain()
|
||||
// Desc: This method is the standard Windows program entry point.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
int APIENTRY WinMain(HINSTANCE hInstance,
|
||||
HINSTANCE hPrevInstance,
|
||||
PSTR pCmdLine,
|
||||
int nCmdShow)
|
||||
{
|
||||
DbgInitialise(hInstance);
|
||||
g_App.SetAppValues(hInstance, APPNAME, IDS_APP_TITLE) ;
|
||||
|
||||
// Perform application initialization:
|
||||
if (! g_App.InitInstance(nCmdShow) )
|
||||
{
|
||||
DbgTerminate();
|
||||
return (FALSE) ;
|
||||
}
|
||||
|
||||
HACCEL hAccelTable ;
|
||||
hAccelTable = LoadAccelerators(hInstance, g_App.GetAppName()) ;
|
||||
|
||||
// Main message loop:
|
||||
MSG msg ;
|
||||
while (GetMessage(&msg, NULL, 0, 0))
|
||||
{
|
||||
if (! TranslateAccelerator(msg.hwnd, hAccelTable, &msg) )
|
||||
{
|
||||
TranslateMessage(&msg) ;
|
||||
DispatchMessage(&msg) ;
|
||||
}
|
||||
}
|
||||
|
||||
DbgTerminate();
|
||||
return (msg.wParam) ;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Name: CApp::CApp()
|
||||
// Desc: This is the constructor for CApp. It sets default values and disables
|
||||
// power saving.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
CApp::CApp() : m_hInstance(NULL),
|
||||
m_hWnd(NULL),
|
||||
m_bCaptionsOn(false),
|
||||
m_pDvdCore(NULL),
|
||||
m_bFullScreenOn(false),
|
||||
m_pParentLevels(NULL),
|
||||
m_pLangLookup(NULL),
|
||||
m_hwndToolBar(0),
|
||||
m_dwProhibitedTime(0)
|
||||
{
|
||||
DbgLog((LOG_TRACE, 5, TEXT("CApp::CApp()"))) ;
|
||||
ZeroMemory(m_szAppTitle, sizeof(m_szAppTitle)) ;
|
||||
|
||||
ZeroMemory(m_szAppName, sizeof(m_szAppName)) ;
|
||||
|
||||
m_pParentLevels = new CParentLevels();
|
||||
m_pLangLookup = new CDVDLanguages();
|
||||
|
||||
// notify the power manager that the display is in use so it won't go to sleep
|
||||
// SetThreadExecutionState() is a Win98/Win2k API.
|
||||
// The following code lets it fail gracefully on Win95
|
||||
|
||||
PFNDLL_STES pfn;
|
||||
pfn = (PFNDLL_STES) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),
|
||||
"SetThreadExecutionState");
|
||||
if (pfn)
|
||||
{
|
||||
pfn(ES_CONTINUOUS | ES_DISPLAY_REQUIRED);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Name: CApp::~CApp()
|
||||
// Desc: This is the destructor for CApp.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
CApp::~CApp()
|
||||
{
|
||||
DbgLog((LOG_TRACE, 5, TEXT("CApp::~CApp()"))) ;
|
||||
|
||||
delete m_pParentLevels;
|
||||
delete m_pLangLookup;
|
||||
if (m_pDvdCore)
|
||||
{
|
||||
delete m_pDvdCore;
|
||||
m_pDvdCore = NULL;
|
||||
}
|
||||
|
||||
// notify the power manager that the display is no longer in use and it can go to sleep
|
||||
// SetThreadExecutionState() is a Win98/Win2k API.
|
||||
// The following code lets it fail gracefully on Win95
|
||||
|
||||
PFNDLL_STES pfn;
|
||||
pfn = (PFNDLL_STES) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),
|
||||
"SetThreadExecutionState");
|
||||
if (pfn)
|
||||
{
|
||||
pfn(ES_CONTINUOUS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Name: CApp::SetAppValues()
|
||||
// Desc: This method sets the basic application values like szAppName and hInstance
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void CApp::SetAppValues(HINSTANCE hInst, PTSTR szAppName, int iAppTitleResId)
|
||||
{
|
||||
DbgLog((LOG_TRACE, 5, TEXT("CApp::SetAppValues()"))) ;
|
||||
|
||||
// The Windows stuff
|
||||
m_hInstance = hInst ;
|
||||
lstrcpy(m_szAppName, APPNAME) ;
|
||||
LoadString(m_hInstance, IDS_APP_TITLE, m_szAppTitle, 100) ;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Name: CApp::InitInstance()
|
||||
// Desc: This method registers and creates our window and toolbar.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool CApp::InitInstance(int nCmdShow)
|
||||
{
|
||||
DbgLog((LOG_TRACE, 5, TEXT("CApp::InitInstance()"))) ;
|
||||
|
||||
// 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
|
||||
m_hWnd = FindWindow (m_szAppName, m_szAppTitle) ;
|
||||
if (m_hWnd)
|
||||
{
|
||||
// We found another instance of ourself. Lets use that one:
|
||||
if (IsIconic(m_hWnd))
|
||||
{
|
||||
ShowWindow(m_hWnd, SW_RESTORE);
|
||||
}
|
||||
SetForegroundWindow(m_hWnd);
|
||||
|
||||
// If this app actually had any methodality, 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
|
||||
WNDCLASSEX wc ;
|
||||
wc.cbSize = sizeof(wc) ;
|
||||
wc.style = CS_HREDRAW | CS_VREDRAW ;
|
||||
wc.lpfnWndProc = (WNDPROC) WndProc ;
|
||||
wc.cbClsExtra = 0 ;
|
||||
wc.cbWndExtra = 0 ;
|
||||
wc.hInstance = m_hInstance ;
|
||||
wc.hIcon = LoadIcon(m_hInstance, MAKEINTRESOURCE(IDI_APPICON));
|
||||
wc.hCursor = LoadCursor(NULL, IDC_ARROW) ;
|
||||
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1) ;
|
||||
wc.lpszMenuName = TEXT("DvdSample_Menu");
|
||||
wc.lpszClassName = m_szAppName ;
|
||||
wc.hIconSm = NULL ;
|
||||
|
||||
if (0 == RegisterClassEx(&wc))
|
||||
{
|
||||
DbgLog((LOG_ERROR, 0,
|
||||
TEXT("ERROR: RegisterClassEx() for app class failed (Error %ld)"),
|
||||
GetLastError())) ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
// Determine where to put the Application Window
|
||||
RECT rDesktop;
|
||||
SystemParametersInfo(SPI_GETWORKAREA, NULL, &rDesktop, NULL);
|
||||
|
||||
// Create an instance of the window we just registered
|
||||
// locate it at the bottom of the screen (bottom of screen - height of player)
|
||||
m_hWnd = CreateWindowEx(0, m_szAppName, m_szAppTitle, WS_OVERLAPPEDWINDOW, //& ~WS_THICKFRAME,
|
||||
160, rDesktop.bottom - 150, 300, 150, NULL, NULL, m_hInstance, NULL);
|
||||
if (!m_hWnd)
|
||||
{
|
||||
DbgLog((LOG_ERROR, 0,
|
||||
TEXT("ERROR: CreateWindowEx() failed (Error %ld)"),
|
||||
GetLastError())) ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
// We now create the toolbar
|
||||
INITCOMMONCONTROLSEX cc;
|
||||
cc.dwSize = sizeof(INITCOMMONCONTROLSEX);
|
||||
cc.dwICC = ICC_BAR_CLASSES; // register only the toolbar control
|
||||
InitCommonControlsEx(&cc);
|
||||
|
||||
TBBUTTON tbb[] =
|
||||
{
|
||||
0, ID_PLAYBACK_PREVIOUSCHAPTER, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, 0,
|
||||
1, ID_PLAYBACK_REWIND, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, 0,
|
||||
2, ID_PLAYBACK_PAUSE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, 0,
|
||||
3, ID_PLAYBACK_PLAY, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, 0,
|
||||
4, ID_PLAYBACK_STOP, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, 0,
|
||||
5, ID_PLAYBACK_FASTFORWARD, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, 0,
|
||||
6, ID_PLAYBACK_NEXTCHAPTER, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, 0,
|
||||
9, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0, 0, 0,
|
||||
7, ID_PLAYBACK_MENUROOT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, 0,
|
||||
8, ID_OPTIONS_FULLSCREEN, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, 0,
|
||||
9, ID_PLAYBACK_STEPFORWARD, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
m_hwndToolBar = CreateToolbarEx(m_hWnd, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | CCS_TOP
|
||||
| TBSTYLE_TOOLTIPS, 1, 10, m_hInstance, IDR_TOOLBAR1, tbb, 11, 0, 0, 0, 0,
|
||||
sizeof(TBBUTTON));
|
||||
if (!m_hwndToolBar)
|
||||
{
|
||||
DbgLog((LOG_ERROR, 0,
|
||||
TEXT("ERROR: CreateToolbarEx() failed (Error %ld)"),
|
||||
GetLastError())) ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
// we now set up the dvd playback class
|
||||
m_pDvdCore = new CDvdCore(m_hInstance, this);
|
||||
if (!m_pDvdCore->Init())
|
||||
{
|
||||
DbgLog((LOG_ERROR, 0, TEXT("ERROR: CDvdCore::Init() failed"))) ;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_pDvdCore->SetVideoWindowTitle(TEXT("DvdSample Video Window"));
|
||||
|
||||
// and finally, we make the window visible
|
||||
ShowWindow(m_hWnd, nCmdShow);
|
||||
UpdateWindow(m_hWnd) ;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Name: WndProc()
|
||||
// Desc: This method is our main window procedure. It parses the messages
|
||||
// and farms out the work to other procedures.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
LRESULT CApp::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
static HDC hDC ;
|
||||
static PAINTSTRUCT ps ;
|
||||
|
||||
switch (message) {
|
||||
|
||||
case WM_INITMENUPOPUP:
|
||||
// UpdateMenuState() ;
|
||||
break ;
|
||||
|
||||
case WM_PAINT:
|
||||
hDC = BeginPaint(hWnd, &ps) ;
|
||||
ASSERT(hDC) ;
|
||||
g_App.DrawStatus(hDC);
|
||||
EndPaint(hWnd, &ps) ;
|
||||
break ;
|
||||
|
||||
case WM_KEYUP:
|
||||
g_App.KeyProc(wParam, lParam) ;
|
||||
break ;
|
||||
|
||||
case WM_COMMAND:
|
||||
g_App.MenuProc(hWnd, wParam, lParam) ;
|
||||
break;
|
||||
|
||||
case WM_NOTIFY:
|
||||
return g_App.ToolTipProc(hWnd, message, wParam, lParam);
|
||||
break;
|
||||
|
||||
case WM_DESTROY:
|
||||
PostQuitMessage(0);
|
||||
break;
|
||||
|
||||
case WM_SIZE:
|
||||
// we do this to cause the toolbar to resize correctly
|
||||
SendMessage(g_App.m_hwndToolBar, WM_SIZE, wParam, lParam);
|
||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||
break;
|
||||
|
||||
default:
|
||||
return (DefWindowProc(hWnd, message, wParam, lParam));
|
||||
}
|
||||
|
||||
return 0 ; // let Windows know we handled the message
|
||||
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Name: ToolTipProc()
|
||||
// Desc: This method is a MessageProc for our toolbar tooltips.
|
||||
// This checks whether the WM_NOTIFY message is really a tooltip.
|
||||
// If it is, we compare it to the buttons on the toolbar and send the right text back.
|
||||
// Note that older code would use TTN_NEEDTEXT instead of TTN_GETDISPINFO.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
LRESULT CApp::ToolTipProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
DbgLog((LOG_TRACE, 5, TEXT("CApp::ToolTipProc()"))) ;
|
||||
|
||||
LPNMTTDISPINFO TText;
|
||||
TText = (LPNMTTDISPINFO) lParam;
|
||||
if (TTN_GETDISPINFO == TText->hdr.code)
|
||||
{
|
||||
switch (TText->hdr.idFrom)
|
||||
{
|
||||
case ID_PLAYBACK_PREVIOUSCHAPTER:
|
||||
TText->lpszText = TEXT("Previous Chapter");
|
||||
break;
|
||||
case ID_PLAYBACK_REWIND:
|
||||
TText->lpszText = TEXT("Rewind");
|
||||
break;
|
||||
case ID_PLAYBACK_PAUSE:
|
||||
TText->lpszText = TEXT("Pause");
|
||||
break;
|
||||
case ID_PLAYBACK_PLAY:
|
||||
TText->lpszText = TEXT("Play");
|
||||
break;
|
||||
case ID_PLAYBACK_STOP:
|
||||
TText->lpszText = TEXT("Stop");
|
||||
break;
|
||||
case ID_PLAYBACK_FASTFORWARD:
|
||||
TText->lpszText = TEXT("FastForward");
|
||||
break;
|
||||
case ID_PLAYBACK_NEXTCHAPTER:
|
||||
TText->lpszText = TEXT("Next Chapter");
|
||||
break;
|
||||
case ID_PLAYBACK_MENUROOT:
|
||||
TText->lpszText = TEXT("Root Menu / Resume");
|
||||
break;
|
||||
case ID_OPTIONS_FULLSCREEN:
|
||||
TText->lpszText = TEXT("Full Screen");
|
||||
break;
|
||||
case ID_PLAYBACK_STEPFORWARD:
|
||||
TText->lpszText = TEXT("Step Forward");
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return DefWindowProc(hWnd, message, wParam, lParam); // it wasn't a tooltip message
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Name: CApp::MenuProc()
|
||||
// Desc: This method handles all of the menu messages for our application. It is
|
||||
// passed these messages by the main message proc.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
LRESULT CApp::MenuProc(HWND hWnd, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
DbgLog((LOG_TRACE, 5, TEXT("CApp::MenuProc()"))) ;
|
||||
|
||||
HMENU hMenu = GetMenu(hWnd) ;
|
||||
|
||||
//Parse the menu selections:
|
||||
switch (LOWORD(wParam))
|
||||
{
|
||||
case ID_PLAYBACK_PLAY:
|
||||
m_pDvdCore->Play();
|
||||
break;
|
||||
|
||||
case ID_PLAYBACK_PREVIOUSCHAPTER:
|
||||
m_pDvdCore->PrevChapter();
|
||||
break;
|
||||
|
||||
case ID_PLAYBACK_REWIND:
|
||||
m_pDvdCore->Rewind();
|
||||
break;
|
||||
|
||||
case ID_PLAYBACK_PAUSE:
|
||||
m_pDvdCore->Pause();
|
||||
break;
|
||||
|
||||
case ID_PLAYBACK_STOP:
|
||||
m_pDvdCore->Stop();
|
||||
break;
|
||||
|
||||
case ID_PLAYBACK_FASTFORWARD:
|
||||
m_pDvdCore->FastForward();
|
||||
break;
|
||||
|
||||
case ID_PLAYBACK_NEXTCHAPTER:
|
||||
m_pDvdCore->NextChapter();
|
||||
break;
|
||||
|
||||
case ID_PLAYBACK_MENUROOT:
|
||||
m_pDvdCore->RootMenu();
|
||||
break;
|
||||
|
||||
case ID_OPTIONS_FULLSCREEN:
|
||||
{
|
||||
m_pDvdCore->ToggleFullScreen();
|
||||
}
|
||||
break;
|
||||
|
||||
case ID_PLAYBACK_TITLEMENU:
|
||||
m_pDvdCore->TitleMenu();
|
||||
break;
|
||||
|
||||
case ID_FILE_EXIT:
|
||||
DestroyWindow(m_hWnd);
|
||||
break;
|
||||
|
||||
case ID_OPTIONS_CLOSEDCAPTION:
|
||||
if (false == m_bCaptionsOn) // turn them on
|
||||
{
|
||||
HMENU hSubMenu = GetSubMenu(hMenu, 2); // Options is the 3rd menu starting with 0
|
||||
CheckMenuItem(hSubMenu, ID_OPTIONS_CLOSEDCAPTION, MF_BYCOMMAND | MF_CHECKED);
|
||||
if (m_pDvdCore->EnableCaptions(true))
|
||||
m_bCaptionsOn = true;
|
||||
}
|
||||
else // turn them off
|
||||
{
|
||||
HMENU hSubMenu = GetSubMenu(hMenu, 2); // Options is the 3rd menu starting with 0
|
||||
CheckMenuItem(hSubMenu, ID_OPTIONS_CLOSEDCAPTION, MF_BYCOMMAND | MF_UNCHECKED);
|
||||
if (m_pDvdCore->EnableCaptions(false))
|
||||
m_bCaptionsOn = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case ID_OPTIONS_SAVEBOOKMARK:
|
||||
m_pDvdCore->SaveBookmark();
|
||||
break;
|
||||
|
||||
case ID_OPTIONS_RESTOREBOOKMARK:
|
||||
m_pDvdCore->RestoreBookmark();
|
||||
break;
|
||||
|
||||
case ID_OPTIONS_PARENTALLEVEL:
|
||||
if (Nav_Stopped != m_pDvdCore->GetState() && Graph_Stopped2 != m_pDvdCore->GetState())
|
||||
// can't change parental level except in stop state
|
||||
{
|
||||
MessageBox(m_hWnd,
|
||||
TEXT("Can't change parental control level during playback. Please stop (twice) first."),
|
||||
TEXT("Error"), MB_OK | MB_ICONINFORMATION) ;
|
||||
break ;
|
||||
}
|
||||
DialogBox(m_hInstance, MAKEINTRESOURCE(IDD_PARENTLEVELS), m_hWnd,
|
||||
reinterpret_cast<DLGPROC>(SelectParentalLevel));
|
||||
|
||||
break;
|
||||
|
||||
case ID_HELP_ABOUTDVDSAMPLE:
|
||||
{
|
||||
CAboutDlg aDlg(m_hInstance, m_hWnd);
|
||||
aDlg.DoModal();
|
||||
}
|
||||
break;
|
||||
|
||||
case ID_OPTIONS_SUBPICTURE:
|
||||
{
|
||||
CSPLangDlg aDlg(m_hInstance, m_hWnd);
|
||||
aDlg.DoModal();
|
||||
}
|
||||
break;
|
||||
|
||||
case ID_OPTIONS_AUDIOLANGUAGE:
|
||||
{
|
||||
CAudioLangDlg aDlg(m_hInstance, m_hWnd);
|
||||
aDlg.DoModal();
|
||||
}
|
||||
break;
|
||||
|
||||
case ID_OPTIONS_ANGLE:
|
||||
{
|
||||
CAngleDlg aDlg(m_hInstance, m_hWnd);
|
||||
aDlg.DoModal();
|
||||
}
|
||||
break;
|
||||
|
||||
case ID_FILE_SELECTDISC:
|
||||
OnSelectDisc();
|
||||
break;
|
||||
|
||||
case ID_PLAYBACK_STEPFORWARD:
|
||||
m_pDvdCore->FrameStep();
|
||||
break;
|
||||
|
||||
case ID_PLAYBACK_GOTO_CHAPTER:
|
||||
{
|
||||
CChapterDlg aDlg(m_hInstance, m_hWnd);
|
||||
if (false == aDlg.DoModal())
|
||||
break;
|
||||
m_pDvdCore->PlayChapter(aDlg.GetChapter());
|
||||
}
|
||||
break;
|
||||
|
||||
case ID_PLAYBACK_GOTO_TITLE:
|
||||
{
|
||||
CTitleDlg aDlg(m_hInstance, m_hWnd);
|
||||
if (false == aDlg.DoModal())
|
||||
break;
|
||||
m_pDvdCore->PlayChapterInTitle(aDlg.GetTitle(), aDlg.GetChapter());
|
||||
}
|
||||
break;
|
||||
|
||||
case ID_PLAYBACK_GOTO_TIME:
|
||||
{
|
||||
CTimeDlg aDlg(m_hInstance, m_hWnd);
|
||||
|
||||
DVD_HMSF_TIMECODE time = m_pDvdCore->GetTime();
|
||||
aDlg.SetTime(time);
|
||||
|
||||
if (false == aDlg.DoModal())
|
||||
break;
|
||||
m_pDvdCore->PlayTime(aDlg.GetTime());
|
||||
}
|
||||
break;
|
||||
|
||||
case ID_OPTIONS_GETDISCTEXT:
|
||||
m_pDvdCore->GetDvdText();
|
||||
break;
|
||||
|
||||
case ID_OPTIONS_GETAUDIOATTRIBUTES:
|
||||
m_pDvdCore->GetAudioAttributes();
|
||||
break;
|
||||
|
||||
case ID_OPTIONS_GETVIDEOATTRIBUTES:
|
||||
m_pDvdCore->GetVideoAttributes();
|
||||
break;
|
||||
|
||||
case ID_OPTIONS_GETSUBPICTUREATTRIBUTES:
|
||||
m_pDvdCore->GetSPAttributes();
|
||||
break;
|
||||
|
||||
case ID_OPTIONS_SETKARAOKEMIXING:
|
||||
{
|
||||
CKaraokeDlg aDlg(m_hInstance, m_hWnd);
|
||||
aDlg.DoModal(); // all work happens in the dialog code
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Name: CApp::KeyProc()
|
||||
// Desc: This method will process all key presses sent to our application window.
|
||||
// At present it passes all of the keys along to the DvdCore but this is where
|
||||
// you would implement shortcut keys, etc.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
LRESULT CApp::KeyProc(WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
DbgLog((LOG_TRACE, 5, TEXT("CApp::KeyProc()"))) ;
|
||||
|
||||
switch (wParam)
|
||||
{
|
||||
case VK_ESCAPE: // exit full screen
|
||||
case VK_RETURN: // activate the currently selected button
|
||||
case VK_LEFT: // select the left button
|
||||
case VK_RIGHT: // select the right button
|
||||
case VK_UP: // select the upper button
|
||||
case VK_DOWN: // select the lower button
|
||||
return m_pDvdCore->OnKeyEvent(wParam, lParam); // pass these keys on to the Core.
|
||||
}
|
||||
return DefWindowProc(m_hWnd, WM_KEYUP, wParam, lParam);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Name: CApp::SelectParentalLevel()
|
||||
// Desc: This method is the MessageProc for the Parental Level Dialog. It is used
|
||||
// to allow the user to select the parental level setting.
|
||||
//
|
||||
// The Dialog wrapper class is not used to demonstrate an alternate way to
|
||||
// handle dialogs.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
BOOL CALLBACK CApp::SelectParentalLevel(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
DbgLog((LOG_TRACE, 5, TEXT("CApp::SelectParentalLevel()"))) ;
|
||||
|
||||
switch (message)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
g_App.MakeParentLevelList(hDlg, IDC_LEVEL_LIST) ;
|
||||
return TRUE;
|
||||
|
||||
case WM_COMMAND:
|
||||
switch (LOWORD(wParam))
|
||||
{
|
||||
case IDOK:
|
||||
{
|
||||
LONG lLevel ;
|
||||
lLevel = SendDlgItemMessage(hDlg, IDC_LEVEL_LIST, LB_GETCURSEL,
|
||||
static_cast<WPARAM>(0), static_cast<LPARAM>(0) );
|
||||
if (CB_ERR == lLevel)
|
||||
DbgLog((LOG_ERROR, 1, TEXT("WARNING: Couldn't get selected parental control level (Error %d)"), lLevel)) ;
|
||||
else
|
||||
g_App.m_pDvdCore->SetParentalLevel(g_App.m_pParentLevels->GetValue(lLevel)) ;
|
||||
}
|
||||
|
||||
// Now fall through to just end the dialog
|
||||
|
||||
case IDCANCEL:
|
||||
EndDialog(hDlg, TRUE);
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break ;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Name: CApp::UpdateStatus()
|
||||
// Desc: This method is notified every time that status of the player changes
|
||||
// (Time, title, Chapter, etc.). This invalidates the client rectangle to force
|
||||
// a redraw of the screen.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void CApp::UpdateStatus(void)
|
||||
{
|
||||
DbgLog((LOG_TRACE, 5, TEXT("CApp::UpdateStatus()"))) ;
|
||||
|
||||
RECT Rect;
|
||||
if (FALSE != GetClientRect(m_hWnd, &Rect))
|
||||
{
|
||||
Rect.top += 30; // so we don't redraw the toolbar - 30 is just a rough number
|
||||
InvalidateRect(m_hWnd, &Rect, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD res = GetLastError();
|
||||
DbgLog((LOG_ERROR, 1, TEXT("GetClientRect failed: %#x"), res)) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Name: CApp::DrawStatus()
|
||||
// Desc: This method draws our status test (time, title, chapter) on the screen
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void CApp::DrawStatus(HDC hDC)
|
||||
{
|
||||
DbgLog((LOG_TRACE, 5, TEXT("CApp::DrawStatus()"))) ;
|
||||
|
||||
TCHAR location[25];
|
||||
wsprintf(location, TEXT("Title: %-6uChapter: %u"), m_pDvdCore->GetTitle(),
|
||||
m_pDvdCore->GetChapter());
|
||||
TextOut(hDC, 10, 50, location, lstrlen(location));
|
||||
|
||||
TCHAR time[15];
|
||||
wsprintf(time, TEXT("Time: %02d:%02d:%02d"), m_pDvdCore->GetTime().bHours,
|
||||
m_pDvdCore->GetTime().bMinutes, m_pDvdCore->GetTime().bSeconds);
|
||||
TextOut(hDC, 10, 65, time, lstrlen(time));
|
||||
|
||||
if (timeGetTime() <= (m_dwProhibitedTime + 5000)) // if less than 5 seconds has passed
|
||||
{
|
||||
SetTextColor(hDC, RGB(255, 0, 0));
|
||||
TextOut(hDC, 180, 80, TEXT("Prohibited!"), 11);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Name: CApp::OnSelectDisc()
|
||||
// Desc: This method brings up a common file dialog to ask the user to find the
|
||||
// dvd disc they wish to watch. We look for the video_ts.ifo file.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool CApp::OnSelectDisc()
|
||||
{
|
||||
DbgLog((LOG_TRACE, 5, TEXT("CApp::OnSelectDisc()"))) ;
|
||||
|
||||
OPENFILENAME ofn ; // structure used by the common file dialog
|
||||
TCHAR szFileName[MAX_PATH] ;
|
||||
|
||||
// Init the filename buffer with *.ifo
|
||||
lstrcpy(szFileName, TEXT("*.ifo")) ;
|
||||
|
||||
ZeroMemory(&ofn, sizeof(OPENFILENAME)) ;
|
||||
ofn.lStructSize = sizeof(OPENFILENAME) ;
|
||||
ofn.hwndOwner = m_hWnd ;
|
||||
ofn.lpstrFilter = TEXT("IFO Files\0*.ifo\0All Files\0*.*\0") ;
|
||||
ofn.nFilterIndex = 1 ;
|
||||
ofn.lpstrFile = szFileName ;
|
||||
ofn.nMaxFile = sizeof(szFileName) ;
|
||||
ofn.lpstrFileTitle = NULL ;
|
||||
ofn.lpstrTitle = TEXT("Select DVD-Video Volume") ;
|
||||
ofn.nMaxFileTitle = 0 ;
|
||||
ofn.lpstrInitialDir = NULL ;
|
||||
ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY ;
|
||||
|
||||
// GetOpenFileName will bring up the common file dialog in open mode
|
||||
if (GetOpenFileName(&ofn)) // user specified a file
|
||||
{
|
||||
return m_pDvdCore->SetDirectory(szFileName);
|
||||
}
|
||||
|
||||
// Either failed or user hit Esc.
|
||||
DWORD dw = CommDlgExtendedError() ;
|
||||
DbgLog((LOG_TRACE, 3, TEXT("GetOpenFileName() cancelled/failed with error %lu"), dw)) ;
|
||||
|
||||
return false ; // DVD-Video volume not changed
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Name: CApp::Prohibited()
|
||||
// Desc: This method is called by the DVDCore whenever an operation is attempted that
|
||||
// is prohibited by UOP. We set a time value and then invalidate the rectangle.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void CApp::Prohibited()
|
||||
{
|
||||
DbgLog((LOG_TRACE, 5, TEXT("CApp::Prohibited()"))) ;
|
||||
|
||||
m_dwProhibitedTime = timeGetTime();
|
||||
|
||||
RECT Rect;
|
||||
if (FALSE != GetClientRect(m_hWnd, &Rect))
|
||||
{
|
||||
Rect.top += 30; // so we don't redraw the toolbar - 30 is just a rough number
|
||||
InvalidateRect(m_hWnd, &Rect, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD res = GetLastError();
|
||||
DbgLog((LOG_ERROR, 1, TEXT("GetClientRect failed: %#x"), res)) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Name: CApp::Exit()
|
||||
// Desc: This method is part of IDvdCallBack. It is called by the DVDCore whenever
|
||||
// the playback window si closed. We then close down the application.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void CApp::Exit()
|
||||
{
|
||||
DbgLog((LOG_TRACE, 5, TEXT("CApp::Exit()"))) ;
|
||||
PostQuitMessage(0);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Name: CApp::GetAppWindow()
|
||||
// Desc: This method is a member of IDVDCallback. It returns the location and size
|
||||
// of the player window to the application.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
RECT CApp::GetAppWindow()
|
||||
{
|
||||
RECT rWindow;
|
||||
GetWindowRect(m_hWnd, &rWindow);
|
||||
return rWindow;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Name: CApp::MakeParentLevelList()
|
||||
// Desc: This method creates a list of parental levels and adds them to the
|
||||
// parental level dialog box's listbox.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
int CApp::MakeParentLevelList(HWND hDlg, int iListID)
|
||||
{
|
||||
DbgLog((LOG_TRACE, 5, TEXT("CApp::MakeParentalLevelList(0x%lx, %d)"),
|
||||
hDlg, iListID)) ;
|
||||
|
||||
int iLevels = m_pParentLevels->GetCount() ;
|
||||
int iResult ;
|
||||
|
||||
// add all defined parental levels
|
||||
for (int i = 0 ; i < iLevels ; i++)
|
||||
{
|
||||
// Add to the listbox now
|
||||
iResult = SendDlgItemMessage(hDlg, iListID, LB_ADDSTRING, (WPARAM) 0,
|
||||
(LPARAM)(LPVOID) m_pParentLevels->GetName(i)) ;
|
||||
if (LB_ERR == iResult || LB_ERRSPACE == iResult)
|
||||
{
|
||||
DbgLog((LOG_ERROR, 1,
|
||||
TEXT("Error (%d) adding parental level '%s'(%d) to list"),
|
||||
iResult, m_pParentLevels->GetName(i), i)) ;
|
||||
}
|
||||
}
|
||||
|
||||
if (iLevels > 0)
|
||||
{
|
||||
iResult = SendDlgItemMessage(hDlg, iListID, LB_SETCURSEL,
|
||||
(WPARAM) m_pDvdCore->GetParentalLevel(), (LPARAM) 0) ;
|
||||
if (LB_ERR == iResult)
|
||||
{
|
||||
DbgLog((LOG_ERROR, 1,
|
||||
TEXT("WARNING: Couldn't set %ld as selected parent level (Error %d)"),
|
||||
m_ulParentCtrlLevel, iResult)) ;
|
||||
}
|
||||
}
|
||||
return iLevels ;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Name: CDVDLanguages::CDVDLanguages()
|
||||
// Desc: This is the constructor. It sets up our lookup table
|
||||
// Only 10 languages have been used here as a sample.
|
||||
// The list can be extended to include any language listed in ISO 639.
|
||||
//------------------------------------------------------------------------------
|
||||
CDVDLanguages::CDVDLanguages()
|
||||
{
|
||||
DbgLog((LOG_TRACE, 5, TEXT("CDVDLanguages::CDVDLanguages()"))) ;
|
||||
|
||||
m_lcidCodes[0] = 0x0407 ; m_apszLangNames[0] = TEXT("German") ;
|
||||
m_lcidCodes[1] = 0x0409 ; m_apszLangNames[1] = TEXT("English") ;
|
||||
m_lcidCodes[2] = 0x040a ; m_apszLangNames[2] = TEXT("Spanish") ;
|
||||
m_lcidCodes[3] = 0x040c ; m_apszLangNames[3] = TEXT("French") ;
|
||||
m_lcidCodes[4] = 0x0411 ; m_apszLangNames[4] = TEXT("Japanese") ;
|
||||
m_lcidCodes[5] = 0x0412 ; m_apszLangNames[5] = TEXT("Korean") ;
|
||||
m_lcidCodes[6] = 0x0413 ; m_apszLangNames[6] = TEXT("Dutch") ;
|
||||
m_lcidCodes[7] = 0x0816 ; m_apszLangNames[7] = TEXT("Portuguese") ;
|
||||
m_lcidCodes[8] = 0x041d ; m_apszLangNames[8] = TEXT("Swedish") ;
|
||||
m_lcidCodes[9] = 0x0804 ; m_apszLangNames[9] = TEXT("Chinese") ;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Name: CDVDLanguages::GetLangString()
|
||||
// Desc: This method is our lookup function. It takes an LCID language code
|
||||
// and returns an English string language name.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool CDVDLanguages::GetLangString(LCID LangCode, PTSTR pszLang, int iMaxLen)
|
||||
{
|
||||
DbgLog((LOG_TRACE, 5, TEXT("CDVDLanguages::GetLangString()"))) ;
|
||||
|
||||
for (int i = 0 ; i < 10 ; i++)
|
||||
{
|
||||
if (LangCode == m_lcidCodes[i]) // match!!
|
||||
{
|
||||
if (iMaxLen < lstrlen(m_apszLangNames[i]))
|
||||
{
|
||||
lstrcpy(pszLang, m_apszLangNames[i]) ;
|
||||
return true ; // got a match
|
||||
}
|
||||
// let it fall through if that fails
|
||||
}
|
||||
}
|
||||
if (iMaxLen < lstrlen(TEXT("Unknown")))
|
||||
{
|
||||
lstrcpy(pszLang, TEXT("Unknown")) ;
|
||||
}
|
||||
return false ; // didn't get a match
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Name: CParentLevels::CParentLevels()
|
||||
// Desc: This is the constructor for CParentLevels. It can be modified to change
|
||||
// the parental levels shown to the user.
|
||||
// Remember that the mapping of parental levels to MPAA ratings shown here
|
||||
// is only valid for the U.S. and Canada. In other countries, the parental
|
||||
// levels will have different specific meanings, although parental level 1
|
||||
// is always the least restrictive level and level 8 is the most restrictive.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
CParentLevels::CParentLevels()
|
||||
{
|
||||
DbgLog((LOG_TRACE, 5, TEXT("CParentLevels::CParentLevels()"))) ;
|
||||
|
||||
m_iCount = LEVELS ;
|
||||
m_alpszNames[0] = TEXT(" G ") ; m_aiValues[0] = 1 ;
|
||||
m_alpszNames[1] = TEXT(" PG ") ; m_aiValues[1] = 3 ;
|
||||
m_alpszNames[2] = TEXT(" PG-13 ") ; m_aiValues[2] = 4 ;
|
||||
m_alpszNames[3] = TEXT(" R ") ; m_aiValues[3] = 6 ;
|
||||
m_alpszNames[4] = TEXT(" NC-17 ") ; m_aiValues[4] = 7 ;
|
||||
m_alpszNames[5] = TEXT(" Not Rated ") ; m_aiValues[5] = 8 ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user