home *** CD-ROM | disk | FTP | other *** search
- //------------------------------------------------------------------------------
- // File: DvdCore.cpp
- //
- // Desc: Actual implementation of DVD Playback capabilities
- //
- // Copyright (c) 1999-2000, Microsoft Corporation. All rights reserved.
- //------------------------------------------------------------------------------
-
- #include <dshow.h>
- #include <IL21Dec.h>
- #include "resource.h"
- #include "DvdCore.h"
- #include <TCHAR.H>
- #include "StringUtil.h"
- #include <sstream> // STL String library
- using namespace std;
-
- // Error message displayed if no DVD decoder is installed
- #define MSG_NO_DECODER TEXT \
- ("The DVD sample could not locate a DVD decoder on your system.\r\n\r\n" \
- "You must install a third-party DirectShow-compatible MPEG-2 decoder,\r\n" \
- "either software or hardware-based. Microsoft does not supply an MPEG2\r\n" \
- "decoder with DirectShow or as an operating system component.\r\n\r\n" \
- "Please contact your DVD or PC manufacturer for a DVD decoder.\r\n\r\n" \
- "This sample will now exit.")
-
-
-
- //------------------------------------------------------------------------------
- // File-specific data
- //------------------------------------------------------------------------------
-
- namespace // empty namespace means these are only available within this .cpp file
- {
- const WCHAR g_szBookmarkFilename[] = L"c:\\DVDSample.bmk";
- const WCHAR g_szBookmarkName[] = L"DVDSampleBookmarks";
- HHOOK g_hMouse = 0;
- const UINT MOUSETIMER = 1; // the number is arbitrary, it just can't be 0.
- const DWORD MOUSE_TIMEOUT = 5000; // the mouse should disappear after 5 seconds
- }
-
-
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::CDvdCore()
- // Desc: This is our constructor. It initializes all of our variables and initializes
- // the COM subsystem.
- //------------------------------------------------------------------------------
-
- CDvdCore::CDvdCore(HINSTANCE hInstance, IDvdCallback * pIDC) :
- m_dwRenderFlags(AM_DVD_HWDEC_PREFER),
- m_eState(Uninitialized),
- m_pIDvdGB(NULL),
- m_pIDvdC2(NULL),
- m_pIDvdI2(NULL),
- m_pGraph(NULL),
- m_pIVW(NULL),
- m_pIME(NULL),
- m_pIMC(NULL),
- m_hInstance(hInstance),
- m_pIL21Dec(NULL),
- m_hWnd(NULL),
- m_dwMouseMoveTime(0),
- m_bFirstPlay(true),
- m_bFullScreenOn(false),
- m_ulCurTitle(0),
- m_ulCurChapter(0),
- m_bMessageSink(false)
- {
- DbgLog((LOG_TRACE, 5, TEXT("CDvdCore::CDvdCore()"))) ;
-
- CoInitialize(NULL);
- ZeroMemory(m_szDiscPath, sizeof(m_szDiscPath)) ;
- ZeroMemory(&m_CurTime, sizeof(m_CurTime));
-
- // if we are given a valid pointer we will use it, otherwise we point to ourself.
- if (NULL != pIDC)
- m_pCallback = pIDC;
- else
- m_pCallback = this;
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::~CDvdCore()
- // Desc: This is our destructor. It release all of our COM interfaces and closes
- // down the COM subsystem.
- //------------------------------------------------------------------------------
-
- CDvdCore::~CDvdCore()
- {
- DbgLog((LOG_TRACE, 5, TEXT("CDvdCore::~CDvdCore()"))) ;
-
- if (m_bMessageSink) // we set up the message sink and so we need to tear it down
- UnInitMessageSink();
-
- ReleaseInterfaces();
- CoUninitialize();
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::BuildGraph()
- // Desc: This method builds the DVD graph and initializes all of the interface pointers
- // we will need.
- //------------------------------------------------------------------------------
-
- bool CDvdCore::BuildGraph()
- {
- DbgLog((LOG_TRACE, 5, TEXT("CDvdCore::BuildGraph()"))) ;
-
- // First release any existing interface pointer(s)
- ReleaseInterfaces() ;
-
- HRESULT hr;
- hr = CoCreateInstance( CLSID_DvdGraphBuilder,
- NULL,
- CLSCTX_INPROC_SERVER,
- IID_IDvdGraphBuilder,
- reinterpret_cast<void**>(&m_pIDvdGB));
- if (FAILED(hr)) // IDvdGraphBuilder not successfully instantiated
- {
- DbgLog((LOG_ERROR, 0,
- TEXT("ERROR: CoCreateInstance() for CLSID_DvdGraphBuilder failed (Error 0x%x)"),
- hr)) ;
- return false;
- }
-
- SetState(Uninitialized) ;
-
- // Check if a DVD-Video volume name has been specified; if so, use that
- WCHAR szwDiscPath[MAX_PATH] ;
- PCWSTR pszwDiscPath = NULL ; // by default
- if (lstrlen(m_szDiscPath) > 0) // if something was specified before
- {
- #ifdef UNICODE
- lstrcpy(szwDiscPath, m_szDiscPath) ;
- #else
- MultiByteToWideChar(CP_ACP, 0, m_szDiscPath, -1, szwDiscPath, MAX_PATH) ;
- #endif // UNICODE
-
- pszwDiscPath = szwDiscPath ;
- }
-
- // Build the Graph
- AM_DVD_RENDERSTATUS buildStatus;
- DbgLog((LOG_TRACE, 5, TEXT("Calling RenderDvdVideoVolume(<%s>, 0x%lx, 0x%lx)"),
- m_szDiscPath, m_dwRenderFlags, &buildStatus)) ;
- hr = m_pIDvdGB->RenderDvdVideoVolume(pszwDiscPath, m_dwRenderFlags, &buildStatus);
-
- if (FAILED(hr)) // total failure
- {
- // If there is no DVD decoder, give a user-friendly message
- if (hr == 0x8004027b)
- {
- MessageBox(NULL, MSG_NO_DECODER, TEXT("Can't initialize DVD sample"), MB_OK);
- }
- else
- {
- TCHAR szBuffer[100];
- AMGetErrorText(hr, szBuffer, sizeof(szBuffer));
- MessageBox(NULL, szBuffer, TEXT("RenderDvdVideoVolume Failed!"), MB_OK);
- }
- DbgLog((LOG_ERROR, 0,
- TEXT("ERROR: RenderDvdVideoVolume() completely failed (Error 0x%x - %s)"),
- hr, szBuffer)) ;
- return false;
- }
-
- if (S_FALSE == hr) // partial success
- {
- TCHAR szStatusText[1000] ;
- if (0 == GetStatusText(&buildStatus, szStatusText, sizeof(szStatusText)))
- {
- lstrcpy(szStatusText, TEXT("An unknown error has occurred")) ;
- }
- lstrcat(szStatusText, TEXT("\n\nDo you still want to continue?")) ;
- if (IDNO == MessageBox(NULL, szStatusText, TEXT("Warning"), MB_YESNO))
- {
- return false ;
- }
- }
-
- // The graph was successfully rendered in some form if we get this far
- // We will now instantiate all of the necessary interfaces
-
- hr = m_pIDvdGB->GetDvdInterface(IID_IDvdInfo2, reinterpret_cast<void**>(&m_pIDvdI2));
- if (FAILED(hr))
- {
- IDvdInfo *pDvdI ;
- hr = m_pIDvdGB->GetDvdInterface(IID_IDvdInfo, reinterpret_cast<void**>(&pDvdI)) ;
- if (SUCCEEDED(hr))
- {
- MessageBox(NULL,
- TEXT("This version of the application cannot run using\n")
- TEXT("the current DirectShow components. Please use the\n")
- TEXT("DVDSampl.exe application."),
- TEXT("DVD Error!"), MB_OK) ;
- pDvdI->Release() ;
- }
- else
- {
- MessageBox(NULL,
- TEXT("Cannot get the IDvdInfo/IDvdInfo2 interface.")
- TEXT("Sorry, can't play DVD-Video titles."),
- TEXT("DVD Error!"), MB_OK) ;
- }
-
- return false ;
- }
-
- hr = m_pIDvdGB->GetDvdInterface(IID_IDvdControl2, reinterpret_cast<void**>(&m_pIDvdC2));
- if (FAILED(hr))
- {
- IDvdControl *pDvdC ;
- hr = m_pIDvdGB->GetDvdInterface(IID_IDvdControl, reinterpret_cast<void**>(&pDvdC)) ;
- if (SUCCEEDED(hr))
- {
- MessageBox(NULL,
- TEXT("This version of the application cannot run using\n")
- TEXT("the current DirectShow components. Please use the\n")
- TEXT("DVDSampl.exe application."),
- TEXT("DVD Error!"), MB_OK) ;
- pDvdC->Release() ;
- }
- else
- {
- MessageBox(NULL,
- TEXT("Cannot get the IDvdControl/IDvdControl2 interface.")
- TEXT("Sorry, can't play DVD-Video titles."),
- TEXT("DVD Error!"), MB_OK) ;
- }
-
- return false ;
- }
-
- hr = m_pIDvdGB->GetFiltergraph(&m_pGraph);
- if (FAILED(hr))
- {
- MessageBox(NULL,
- TEXT("Cannot get the IGraphBuilder interface.")
- TEXT("Sorry, can't play DVD-Video titles."),
- TEXT("DVD Error!"), MB_OK) ;
-
- return false ;
- }
-
- hr = m_pGraph->QueryInterface(IID_IMediaControl, reinterpret_cast<void**>(&m_pIMC));
- if (FAILED(hr))
- {
- MessageBox(NULL,
- TEXT("Cannot get the IMediaControl interface.")
- TEXT("Sorry, can't play DVD-Video titles."),
- TEXT("DVD Error!"), MB_OK) ;
-
- return false ;
- }
-
- hr = m_pGraph->QueryInterface(IID_IMediaEventEx, reinterpret_cast<void**>(&m_pIME)) ;
- if (FAILED(hr))
- {
- MessageBox(NULL,
- TEXT("Cannot get the MediaEventEx interface.")
- TEXT("Sorry, can't play DVD-Video titles."),
- TEXT("DVD Error!"), MB_OK) ;
-
- return false ;
- }
-
- hr = m_pIDvdGB->GetDvdInterface(IID_IVideoWindow, reinterpret_cast<void**>(&m_pIVW));
- if (FAILED(hr))
- {
- MessageBox(NULL,
- TEXT("Cannot get the IVideoWindow interface.")
- TEXT("Sorry, can't play DVD-Video titles."),
- TEXT("DVD Error!"), MB_OK) ;
-
- return false ;
- }
-
- // this one may or may not be present
- m_pIDvdGB->GetDvdInterface(IID_IAMLine21Decoder, reinterpret_cast<void**>(&m_pIL21Dec));
-
-
- SetState(Graph_Stopped2);
- return true;
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::ReleaseInterfaces()
- // Desc: This method releases all of our COM interfaces
- // This will be called before building a graph and during destruction of the class
- //------------------------------------------------------------------------------
-
- void CDvdCore::ReleaseInterfaces()
- {
- DbgLog((LOG_TRACE, 5, TEXT("CDvdCore::ReleaseInterfaces()"))) ;
-
- if (NULL != m_pGraph)
- {
- m_pGraph->Release();
- m_pGraph = NULL;
- }
-
- if (NULL != m_pIDvdC2)
- {
- m_pIDvdC2->Release();
- m_pIDvdC2 = NULL;
- }
-
- if (NULL != m_pIDvdGB)
- {
- m_pIDvdGB->Release();
- m_pIDvdGB = NULL;
- }
-
- if (NULL != m_pIDvdI2)
- {
- m_pIDvdI2->Release();
- m_pIDvdI2 = NULL;
- }
-
- if (NULL != m_pIL21Dec)
- {
- m_pIL21Dec->Release();
- m_pIL21Dec = NULL;
- }
-
- if (NULL != m_pIMC)
- {
- m_pIMC->Release();
- m_pIMC = NULL;
- }
-
- if (NULL != m_pIME)
- {
- m_pIME->SetNotifyWindow(NULL, WM_DVD_EVENT, 0); // we don't want messages any more
- m_pIME->Release();
- m_pIME = NULL;
- }
-
- if (NULL != m_pIVW)
- {
- m_pIVW->put_Owner(NULL); // make sure we send messages back to the right place
- m_pIVW->Release();
- m_pIVW = NULL;
- }
-
- SetState(Uninitialized);
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::Init()
- // Desc: This method initializes the DVD Playback Core. It provides a means to
- // divide the work among several functions.
- //------------------------------------------------------------------------------
-
- bool CDvdCore::Init()
- {
- DbgLog((LOG_TRACE, 5, TEXT("CDvdCore::Init()"))) ;
-
- if (false == BuildGraph())
- {
- ReleaseInterfaces();
- return false;
- }
- if (false == InitMessageSink())
- return false;
- return SetPlaybackOptions();
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::GetStatusText()
- // Desc: This method parses AM_DVD_RENDERSTATUS and returns a text description of the error
- //------------------------------------------------------------------------------
-
- DWORD CDvdCore::GetStatusText(AM_DVD_RENDERSTATUS *pStatus, PTSTR pszStatusText, DWORD dwMaxText)
- {
- DbgLog((LOG_TRACE, 5, TEXT("CDvdCore::GetStatusText()"))) ;
-
- TCHAR szBuffer[1000] ;
-
- if (IsBadWritePtr(pszStatusText, sizeof(*pszStatusText) * dwMaxText))
- {
- DbgLog((LOG_ERROR, 0, TEXT("GetStatusText(): bad text buffer param"))) ;
- return 0 ;
- }
-
- int iChars ;
- PTSTR pszBuff = szBuffer ;
- ZeroMemory(szBuffer, sizeof(TCHAR) * 1000) ;
- if (pStatus->iNumStreamsFailed > 0)
- {
- iChars = wsprintf(pszBuff,
- TEXT("* %d out of %d DVD-Video streams failed to render properly\n"),
- pStatus->iNumStreamsFailed, pStatus->iNumStreams) ;
- pszBuff += iChars ;
-
- if (pStatus->dwFailedStreamsFlag & AM_DVD_STREAM_VIDEO)
- {
- iChars = wsprintf(pszBuff, TEXT(" - video stream\n")) ;
- pszBuff += iChars ;
- }
- if (pStatus->dwFailedStreamsFlag & AM_DVD_STREAM_AUDIO)
- {
- iChars = wsprintf(pszBuff, TEXT(" - audio stream\n")) ;
- pszBuff += iChars ;
- }
- if (pStatus->dwFailedStreamsFlag & AM_DVD_STREAM_SUBPIC)
- {
- iChars = wsprintf(pszBuff, TEXT(" - subpicture stream\n")) ;
- pszBuff += iChars ;
- }
- }
-
- if (FAILED(pStatus->hrVPEStatus))
- {
- lstrcat(pszBuff, TEXT("* ")) ;
- pszBuff += lstrlen(TEXT("* ")) ;
- iChars = AMGetErrorText(pStatus->hrVPEStatus, pszBuff, 200) ;
- pszBuff += iChars ;
- lstrcat(pszBuff, TEXT("\n")) ;
- pszBuff += lstrlen(TEXT("\n")) ;
- }
-
- if (pStatus->bDvdVolInvalid)
- {
- iChars = wsprintf(pszBuff, TEXT("* Specified DVD-Video volume was invalid\n")) ;
- pszBuff += iChars ;
- }
- else if (pStatus->bDvdVolUnknown)
- {
- iChars = wsprintf(pszBuff, TEXT("* No valid DVD-Video volume could be located\n")) ;
- pszBuff += iChars ;
- }
-
- if (pStatus->bNoLine21In)
- {
- iChars = wsprintf(pszBuff, TEXT("* The video decoder doesn't produce closed caption data\n")) ;
- pszBuff += iChars ;
- }
- if (pStatus->bNoLine21Out)
- {
- iChars = wsprintf(pszBuff, TEXT("* Decoded closed caption data not rendered properly\n")) ;
- pszBuff += iChars ;
- }
-
- DWORD dwLength = (pszBuff - szBuffer) * sizeof(*pszBuff) ;
- dwLength = min(dwLength, dwMaxText) ;
- lstrcpyn(pszStatusText, szBuffer, dwLength) ;
-
- return dwLength ;
-
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::Play()
- // Desc: This method begins DVD Playback
- //------------------------------------------------------------------------------
-
- HRESULT CDvdCore::Play()
- {
- DbgLog((LOG_TRACE, 5, TEXT("CDvdCore::Play()"))) ;
-
- if (true == m_bFirstPlay)
- {
- // now show the playback window
- ShowWindow(m_hWnd, SW_SHOWNORMAL);
- UpdateWindow(m_hWnd) ;
- m_bFirstPlay = false;
- }
-
- HRESULT hr;
-
- switch (m_eState)
- {
- case Uninitialized:
- return E_FAIL;
-
- case Graph_Stopped2:
- hr = m_pIMC->Run();
- m_pIDvdC2->PlayForwards(1.0, 0, NULL); // this call will likely fail due to timing issues. Ignore it.
- if (SUCCEEDED(hr))
- SetState(Playing);
- return hr;
-
- case Nav_Stopped:
- case Graph_Stopped1:
- //hr = m_pIDvdC2->PlayTitle(1, DVD_CMD_FLAG_None, NULL); // play title 1
- hr = m_pIMC->Run();
- if (SUCCEEDED(hr))
- SetState(Playing);
- return hr;
-
- case Graph_Paused:
- m_pIDvdC2->PlayForwards(1.0, 0, NULL);
- hr = m_pIMC->Run();
- if (SUCCEEDED(hr))
- SetState(Playing);
- return hr;
-
- case Nav_Paused:
- m_pIDvdC2->PlayForwards(1.0, 0, NULL);
- hr = m_pIDvdC2->Pause(FALSE);
- if (SUCCEEDED(hr))
- SetState(Playing);
- return hr;
-
- case Playing:
- if (true == m_bStillOn) // we are at a still without buttons
- {
- hr = m_pIDvdC2->StillOff();
- if (SUCCEEDED(hr))
- m_bStillOn = false;
- }
- return hr;
-
- case Scanning:
- hr = m_pIDvdC2->PlayForwards(1.0, 0, NULL);
- if (SUCCEEDED(hr))
- SetState(Playing);
- return hr;
- }
-
- return S_OK;
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::InitMessageSink()
- // Desc: This method creates a parent window and initializes sinks for mouse
- // messages and DVD events.
- // We create a new window instead of just using the IVideoWindow window is
- // that we lose the ability to resize the Video Window once we set up a
- // message drain. The message drain is necessary to handle mouse events for
- // the menus but causes the automatic resizing and movement of the original
- // window to stop working.
- //------------------------------------------------------------------------------
-
- bool CDvdCore::InitMessageSink()
- {
- DbgLog((LOG_TRACE, 5, TEXT("CDvdCore::InitMessageSink()"))) ;
-
- // register playback window
- WNDCLASSEX wndclass = {
- sizeof(WNDCLASSEX),
- CS_HREDRAW | CS_VREDRAW,
- CDvdCore::WndProc,
- 0,
- 0,
- m_hInstance,
- LoadIcon(m_hInstance, MAKEINTRESOURCE(IDI_APPICON)),
- LoadCursor(NULL, IDC_ARROW),
- HBRUSH(COLOR_WINDOW+1),
- NULL,
- TEXT("EventWindow"),
- NULL
- };
-
- RegisterClassEx(&wndclass);
-
- // create the playback window
-
- RECT rPlayback = GetPlaybackWindowRect();
-
- m_hWnd = CreateWindow(
- TEXT("EventWindow"),
- TEXT("Video Window"),
- WS_OVERLAPPEDWINDOW,
- rPlayback.left,
- rPlayback.top,
- rPlayback.right - rPlayback.left,
- rPlayback.bottom - rPlayback.top,
- NULL,
- NULL,
- m_hInstance,
- this); // we send the this pointer here so we can retrieve it from WM_CREATE later
-
- // store the pointer to this instance of CDvdCore.
- // this is so we can refer to it in the OnDvdEvent message loop
- // For win64 compatibily, use SetWindowLongPtr...
- //SetWindowLongPtr(m_hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
- SetWindowLong(m_hWnd, GWL_USERDATA, reinterpret_cast<long>(this));
-
- // set up the event notification so that the dummy window gets
- // informed about DVD events about during playback.
- HRESULT hr;
- hr = m_pIME->SetNotifyWindow(reinterpret_cast<OAHWND>(m_hWnd), WM_DVD_EVENT, 0);
- ASSERT(SUCCEEDED(hr));
-
- // Make the video window a child of the playback window. We do this so we can trap
- // mouse events and still be able to manipulate the window.
- long lStyle;
- m_pIVW->get_WindowStyle(&lStyle);
- m_pIVW->put_WindowStyle( (lStyle | WS_CHILD) & ~(WS_CAPTION | WS_BORDER | WS_THICKFRAME) );
- m_pIVW->put_Owner(reinterpret_cast<OAHWND>(m_hWnd));
- RECT rect;
- GetClientRect(m_hWnd, &rect);
- m_pIVW->SetWindowPosition(0, 0, rect.right, rect.bottom);
-
- // This will cause our playback window to get mouse and keyboard events from the
- // Video Window
- hr = m_pIVW->put_MessageDrain(reinterpret_cast<OAHWND>(m_hWnd)) ;
- ASSERT(SUCCEEDED(hr)) ;
-
- m_bMessageSink = true; // flag so we will turn this off later
-
- return true;
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::WndProc()
- // Desc: This method is a message loop designed to handle mouse, key, and Dvd event messages
- // Because there is no 'this' pointer in a static method, we do the actual work
- // in CDvdCore non-static methods.
- //------------------------------------------------------------------------------
-
- LRESULT CALLBACK CDvdCore::WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
- {
- // retrieve the pointer to the instance of CDvdCore that this window belongs to
- // because OnDvdEvent is a static method, it doesn't have a this pointer
- CDvdCore * pCore = NULL;
- // For Win64 compatibility, use GetWindowLongPtr (Platform SDK)
- //pCore = reinterpret_cast<CDvdCore *>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
- pCore = reinterpret_cast<CDvdCore *>(GetWindowLong(hWnd, GWL_USERDATA));
-
- if (NULL == pCore)
- // this is really only necessary if you want to react to WM_CREATE messages
- {
- if (WM_CREATE == uMessage)
- // WM_CREATE messages return the last parameter to CreateWindow()
- {
- CREATESTRUCT * pCreate = reinterpret_cast<CREATESTRUCT *>(lParam);
- pCore = reinterpret_cast<CDvdCore *>(pCreate->lpCreateParams);
- }
- else return DefWindowProc(hWnd, uMessage, wParam, lParam);
- }
-
-
- switch (uMessage)
- {
-
- case WM_TIMER:
- return pCore->OnMouseTimer(wParam, lParam);
-
- case WM_SIZE:
- return pCore->OnSize(wParam, lParam);
-
- case WM_KEYUP:
- return pCore->OnKeyEvent(wParam, lParam);
-
- case WM_DVD_EVENT:
- return pCore->OnDvdEvent(uMessage, wParam, lParam);
-
- case WM_MOUSEMOVE:
- case WM_LBUTTONUP:
- case WM_RBUTTONUP:
- case WM_MBUTTONUP:
- //case WM_MOUSEWHEEL:
- return pCore->OnMouseEvent(uMessage, wParam, lParam);
-
- case WM_CLOSE:
- return pCore->OnClose();
- }
- return DefWindowProc(hWnd, uMessage, wParam, lParam);
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::SetPlaybackOptions()
- // Desc: This method sets our default line21, ResetOnStop, Parental controls, etc.
- //------------------------------------------------------------------------------
-
- bool CDvdCore::SetPlaybackOptions()
- {
- DbgLog((LOG_TRACE, 5, TEXT("CDvdCore::SetPlaybackOptions()"))) ;
-
- HRESULT hr;
-
- if (m_pIL21Dec)
- {
- hr = m_pIL21Dec->SetServiceState(AM_L21_CCSTATE_Off) ; // Line21 off by default
- if (FAILED(hr))
- return false;
- }
- else
- {
- DbgLog((LOG_TRACE, 2, TEXT("Line21 Decoder interface not found. Can't CC"))) ;
- }
-
- hr = m_pIDvdC2->SetOption(DVD_ResetOnStop, FALSE); // don't reset on stop
- if (FAILED(hr))
- return false;
-
- hr = m_pIDvdC2->SetOption(DVD_NotifyParentalLevelChange, TRUE); // notify us when parental level changes
- if (FAILED(hr))
- return false;
-
- hr = m_pIDvdC2->SetOption(DVD_HMSF_TimeCodeEvents, TRUE); // use new HMSF timecode format
- if (FAILED(hr))
- return false;
-
- return true;
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::NextChapter()
- // Desc: This method is a wrapper for the PlayNextChapter method.
- // It is not necessary to use the IDvdCmd->WaitForEnd() method here. It is
- // done merely to demonstrate how to use this blocking method.
- //------------------------------------------------------------------------------
-
- bool CDvdCore::NextChapter()
- {
- DbgLog((LOG_TRACE, 5, TEXT("CDvdCore::NextChapter()"))) ;
-
- if (Uninitialized == m_eState)
- return false;
-
- if (Playing == m_eState)
- {
- HRESULT hr;
- IDvdCmd * cmdObj;
- hr = m_pIDvdC2->PlayNextChapter(DVD_CMD_FLAG_None, &cmdObj);
- if (FAILED(hr))
- return false;
- cmdObj->WaitForEnd();
- cmdObj->Release();
- if (SUCCEEDED(hr))
- return true;
- }
- return false;
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::PrevChapter()
- // Desc: This method is a wrapper for the PlayPrevChapter method.
- // It is not necessary to use the DVD_CMD_FLAG_Block flag. It is done
- // merely to demonstrate how to use this blocking method.
- //------------------------------------------------------------------------------
-
- bool CDvdCore::PrevChapter()
- {
- DbgLog((LOG_TRACE, 5, TEXT("CDvdCore::PrevChapter()"))) ;
-
- if (Uninitialized == m_eState)
- return false;
-
- if (Playing == m_eState)
- {
- HRESULT hr;
- hr = m_pIDvdC2->PlayPrevChapter(DVD_CMD_FLAG_Block, NULL);
- if (SUCCEEDED(hr))
- return true;
- }
- return false;
-
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::Stop()
- // Desc: This method merely stops playback. We use IMediaControl->Stop rather than
- // IDvdControl2->Stop because it it easier to recover from.
- //------------------------------------------------------------------------------
-
- bool CDvdCore::Stop()
- {
- DbgLog((LOG_TRACE, 5, TEXT("CDvdCore::Stop()"))) ;
- HRESULT hr;
-
- switch (m_eState)
- {
- case Uninitialized:
- return false;
-
- case Graph_Stopped2:
- hr = m_pIDvdC2->SetOption(DVD_ResetOnStop, TRUE); // do a complete reset
- hr = m_pIMC->Stop(); // just to be sure;
- hr = m_pIDvdC2->SetOption(DVD_ResetOnStop, FALSE); // restore previous settings
- break;
-
- case Playing:
- case Scanning:
- case Nav_Paused:
- case Graph_Paused:
- //hr = m_pIDvdC2->Stop(); // put us in stop domain
- hr = m_pIMC->Pause();
- SetState(Graph_Stopped1);
- break;
-
- case Nav_Stopped:
- case Graph_Stopped1:
- hr = m_pIDvdC2->SetOption(DVD_ResetOnStop, TRUE); // do a complete reset
- hr = m_pIMC->Stop(); // stop the entire graph
- hr = m_pIDvdC2->SetOption(DVD_ResetOnStop, FALSE); // restore previous settings
- SetState(Graph_Stopped2);
- break;
- }
- return true;
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::Rewind()
- // Desc: This method begins fast forwarding the disc. It only tries if the disc
- // is playing or FF/RW'ing already.
- //------------------------------------------------------------------------------
-
- bool CDvdCore::Rewind()
- {
- DbgLog((LOG_TRACE, 5, TEXT("CDvdCore::Rewind()"))) ;
-
- if (Uninitialized == m_eState)
- return false;
-
- if (Playing == m_eState || Scanning == m_eState)
- {
- if (FAILED(m_pIDvdC2->PlayBackwards(8.0, 0, NULL)))
- return false;
- SetState(Scanning);
- return true;
- }
- return false;
- }
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::FastForward()
- // Desc: This method begins rewinding the disc. It only tries if the disc
- // is playing or FF/RW'ing already.
- //------------------------------------------------------------------------------
-
- bool CDvdCore::FastForward()
- {
- DbgLog((LOG_TRACE, 5, TEXT("CDvdCore::FastForward()"))) ;
-
- if (Uninitialized == m_eState)
- return false;
-
- if (Playing == m_eState || Scanning == m_eState)
- {
- if (FAILED(m_pIDvdC2->PlayForwards(8.0, 0, NULL)))
- return false;
- SetState(Scanning);
- return true;
- }
- return false;
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::Pause()
- // Desc: This method pauses if we aren't already paused and unpauses if we are.
- //------------------------------------------------------------------------------
-
- bool CDvdCore::Pause(void)
- {
- DbgLog((LOG_TRACE, 5, TEXT("CDvdCore::Pause()"))) ;
-
- if (Uninitialized == m_eState)
- return false;
-
- // if we are paused at the graph level, call run on the graph
- if (Graph_Paused == m_eState)
- {
- if (FAILED(m_pIMC->Run()))
- return false;
- else
- {
- SetState(Playing);
- return true;
- }
- }
- // if we are paused at the Navigator level, call Pause(false)
- if (Nav_Paused == m_eState)
- {
- if (FAILED(m_pIDvdC2->Pause(false)))
- return false;
- else
- {
- SetState(Playing);
- return true;
- }
- }
- // Anything else, we try to pause at the Nav Level
- // this will fail if we are stopped.
- if (FAILED(m_pIDvdC2->Pause(TRUE)))
- return false;
- else
- {
- SetState(Nav_Paused);
- return true;
- }
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::RootMenu()
- // Desc: This method will either bring us into the root menu or call resume if
- // we are already in a menu. The one caveat is that if we are in the title menu
- // we will resume instead of going to the root menu.
- //------------------------------------------------------------------------------
-
- bool CDvdCore::RootMenu()
- {
- DbgLog((LOG_TRACE, 5, TEXT("CDvdCore::RootMenu()"))) ;
-
- if (Uninitialized == m_eState)
- return false;
-
- if (true == m_bMenuOn)
- {
- // we use flush here merely to show how it might be used. You can call Resume without it.
- if (FAILED(m_pIDvdC2->Resume(DVD_CMD_FLAG_Flush, NULL)))
- return false;
- else
- {
- m_bMenuOn = false;
- SetState(Playing);
- return true;
- }
- }
- else if (Playing == m_eState || Scanning == m_eState)
- {
- IDvdCmd * pObj;
- // it is a good idea to block on Menu commands. This is just one way to do so.
- if (FAILED(m_pIDvdC2->ShowMenu(DVD_MENU_Root, DVD_CMD_FLAG_Flush, &pObj)))
- {
- return false;
- }
- else
- {
- pObj->WaitForEnd();
- pObj->Release();
- m_bMenuOn = true;
- SetState(Playing);
- return true;
- }
- }
- return false; // we can't go to a menu from a stop or paused state
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::EnableFullScreen()
- // Desc: This method will enter and exit fullscreen mode depending on the bool
- // value. We don't use IVideoWindow->putFullScreenMode because
- // it won't handle the mouse correctly.
- //------------------------------------------------------------------------------
-
- bool CDvdCore::ToggleFullScreen()
- {
- DbgLog((LOG_TRACE, 5, TEXT("CDvdCore::ToggleFullScreen()"))) ;
-
- if (false == m_bFullScreenOn)
- {
- return StartFullScreen();
- }
-
- else
- return StopFullScreen();
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::TitleMenu()
- // Desc: This method will either bring us into the root menu or call resume if
- // we are already in a menu. The one caveat is that if we are in the root menu
- // we will resume instead of going to the title menu.
- //------------------------------------------------------------------------------
-
- bool CDvdCore::TitleMenu()
- {
- DbgLog((LOG_TRACE, 5, TEXT("CDvdCore::TitleMenu()"))) ;
-
- if (Uninitialized == m_eState)
- return false;
-
- if (true == m_bMenuOn)
- {
- // we use flush here merely to show how it might be used. You can call Resume without it.
- if (FAILED(m_pIDvdC2->Resume(DVD_CMD_FLAG_Flush, NULL)))
- return false;
- else
- {
- SetState(Playing);
- m_bMenuOn = false;
- return true;
- }
- }
- else if (Playing == m_eState || Scanning == m_eState)
- {
- IDvdCmd * pObj;
- // it is a good idea to block on Menu commands. This is just one way to do so.
- HRESULT hr = m_pIDvdC2->ShowMenu(DVD_MENU_Title, DVD_CMD_FLAG_Flush, &pObj);
- if (FAILED(hr))
- {
- if (VFW_E_DVD_OPERATION_INHIBITED == hr)
- m_pCallback->Prohibited();
- DbgLog((LOG_ERROR, 1, TEXT("CDvdCore::TitleMenu() failed: %#x"), hr)) ;
- return false;
- }
- else
- {
- pObj->WaitForEnd();
- pObj->Release();
- SetState(Playing);
- m_bMenuOn = true;
- return true;
- }
- }
- return false; // we can't go to a menu from a stop or paused state
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::EnableCaptions()
- // Desc: This method turns on or off closed captions (Line 21)
- //------------------------------------------------------------------------------
-
- bool CDvdCore::EnableCaptions(bool bOn)
- {
- DbgLog((LOG_TRACE, 5, TEXT("CDvdCore::EnableCaptions(%s)"), bOn ? TEXT("True") :
- TEXT("False"))) ;
-
- if (NULL == m_pIL21Dec) // if this decoder doesn't support Line 21
- return false;
-
- if (SUCCEEDED(m_pIL21Dec->SetServiceState(bOn ? AM_L21_CCSTATE_On : AM_L21_CCSTATE_Off)))
- return true;
- else return false;
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::SetVideoWindowTitle()
- // Desc: This method sets the Title of the IVideoWindow window
- //------------------------------------------------------------------------------
-
- bool CDvdCore::SetVideoWindowTitle(TCHAR *pszTitle)
- {
- DbgLog((LOG_TRACE, 5, TEXT("CDvdCore::SetVideoWindowTitle()"))) ;
-
- if (TRUE == SetWindowText(m_hWnd, pszTitle))
- return true;
- else return false;
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::SaveBookmark()
- // Desc: This method saves a bookmark on the DVD to the hard drive.
- //------------------------------------------------------------------------------
-
- bool CDvdCore::SaveBookmark()
- {
- DbgLog((LOG_TRACE, 5, TEXT("CDvdCore::SaveBookmark()"))) ;
-
- // we begin by getting a copy of the DVD Navigator's internal state
- HRESULT hr;
- IDvdState * pBookmark;
- hr = m_pIDvdI2->GetState (&pBookmark);
- if (FAILED(hr))
- return false;
-
- // next we serialize (persist) the data to the disc.
- // This always saves to the same bookmark file. It could just as easily
- // save to a different one each time.
- //
- // We could also serialize the data to memory using IPersistMemory if we
- // don't want to persist across different executions of the program.
- IStorage * pStorage;
- IStream * pStream;
- bool bCreateStream = false;
- // first try to open an existing file
- hr = StgOpenStorage(g_szBookmarkFilename, NULL, STGM_WRITE | STGM_SHARE_EXCLUSIVE,
- NULL, 0, &pStorage);
- if (SUCCEEDED(hr))
- {
- // we then open a stream object within that file
- hr = pStorage->OpenStream(g_szBookmarkName, NULL, STGM_WRITE |
- STGM_SHARE_EXCLUSIVE, 0, &pStream);
- if (FAILED(hr))
- {
- pBookmark->Release();
- pStorage->Release();
- return false;
- }
- }
- else // if that fails, try to create a new file
- {
- hr = StgCreateDocfile(g_szBookmarkFilename, STGM_CREATE | STGM_WRITE |
- STGM_SHARE_EXCLUSIVE, 0, &pStorage);
- if (FAILED(hr))
- {
- pBookmark->Release();
- return false;
- }
- // we then create a stream object within that file
- hr = pStorage->CreateStream(g_szBookmarkName, STGM_CREATE | STGM_WRITE |
- STGM_SHARE_EXCLUSIVE, 0, 0, &pStream);
- if (FAILED(hr))
- {
- pBookmark->Release();
- pStorage->Release();
- return false;
- }
- }
-
- // now we tell the bookmark to persist itself into the stream we just created
- IPersistStream * pPersistStream;
- hr = pBookmark->QueryInterface(IID_IPersistStream, reinterpret_cast<void**>(&pPersistStream));
- if (SUCCEEDED(hr))
- {
- hr = OleSaveToStream(pPersistStream, pStream);
- pPersistStream->Release();
- pStorage->Release();
- pStream->Release();
- pBookmark->Release();
-
- if (SUCCEEDED(hr))
- return true;
- else
- return false;
- }
- else
- {
- pBookmark->Release();
- pStorage->Release();
- pStream->Release();
- return false;
- }
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::RestoreBookmark()
- // Desc: This method reads a bookmark file from the disc and restores playback
- // at that location.
- //------------------------------------------------------------------------------
-
- bool CDvdCore::RestoreBookmark()
- {
- DbgLog((LOG_TRACE, 5, TEXT("CDvdCore::RestoreBookmark()"))) ;
-
- // Begin by opening the bookmark file on the drive.
- IStorage * pStorage;
- HRESULT hr = StgOpenStorage(g_szBookmarkFilename, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE,
- NULL, 0, &pStorage);
- if (FAILED(hr))
- return false;
-
- // open a stream object within that file
- IStream * pStream;
- hr = pStorage->OpenStream(g_szBookmarkName, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0,
- &pStream);
- if (FAILED(hr))
- {
- pStorage->Release();
- return false;
- }
-
- // load the bookmark in from the stream
- IDvdState * pBookmark;
- hr = OleLoadFromStream(pStream, IID_IDvdState, reinterpret_cast<void**>(&pBookmark));
- pStream->Release();
- pStorage->Release();
- if (FAILED(hr))
- return false;
-
- // restore bookmark's state in the Navigator
- hr = m_pIDvdC2->SetState(pBookmark, DVD_CMD_FLAG_Block, NULL);
- pBookmark->Release();
-
- if (SUCCEEDED(hr))
- return true;
- else
- return false;
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::StartFullScreen()
- // Desc: This method begins fullscreen playback. It saves the original window
- // information, then stretches the window full screen. We use this rather
- // than IVideoWindow::put_FullScreen() because we have greater control over
- // the mouse this way and can show and hide it at will.
- //------------------------------------------------------------------------------
-
- bool CDvdCore::StartFullScreen()
- {
- DbgLog((LOG_TRACE, 5, TEXT("CDvdCore::StartFullScreen()"))) ;
-
- if (NULL == m_pIVW)
- {
- DbgLog((LOG_ERROR, 0,
- TEXT("CDvdCore::StartFullScreen() -- no IVideoWindow pointer yet"))) ;
- return false ;
- }
-
- HRESULT hr ;
-
- // store the original window position
- LONG lLeft, lTop, lWidth, lHeight ;
- hr = m_pIVW->GetWindowPosition(&lLeft, &lTop, &lWidth, &lHeight) ;
- ASSERT(SUCCEEDED(hr)) ;
- SetRect(&m_RectOrigVideo, lLeft, lTop, lLeft + lWidth, lTop + lHeight) ;
-
- // save the original window style
- hr = m_pIVW->get_WindowStyle(&m_lOrigStyle) ;
- ASSERT(SUCCEEDED(hr)) ;
- hr = m_pIVW->get_WindowStyleEx(&m_lOrigStyleEx) ;
- ASSERT(SUCCEEDED(hr)) ;
-
- // the window can't be a child while it is full screen or it can't be stretched beyond the
- // parent window's borders
- hr = m_pIVW->put_Owner(NULL);
- ASSERT(SUCCEEDED(hr)) ;
-
- // modify the window's style
- hr = m_pIVW->put_WindowStyle(m_lOrigStyle &
- ~(WS_BORDER | WS_CAPTION | WS_THICKFRAME)) ; // remove these styles
- ASSERT(SUCCEEDED(hr)) ;
- hr = m_pIVW->put_WindowStyleEx(m_lOrigStyleEx &
- ~(WS_EX_CLIENTEDGE | WS_EX_STATICEDGE | WS_EX_WINDOWEDGE |
- WS_EX_DLGMODALFRAME) // remove these extended styles
- | WS_EX_TOPMOST) ;
- ASSERT(SUCCEEDED(hr)) ;
-
- // stretch the window to the full size of the screen
- LONG lScrnWidth = GetSystemMetrics(SM_CXSCREEN) ;
- LONG lScrnHeight = GetSystemMetrics(SM_CYSCREEN) ;
- hr = m_pIVW->SetWindowPosition(0, 0, lScrnWidth, lScrnHeight) ;
- ASSERT(SUCCEEDED(hr)) ;
-
- // start a timer for mouse blanking
- m_dwMouseMoveTime = timeGetTime();
- SetTimer(m_hWnd, MOUSETIMER, 2500, NULL);
-
- m_bFullScreenOn = true;
-
- return true ;
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::StopFullScreen()
- // Desc: This method restores the Video Window to its original size and style.
- //------------------------------------------------------------------------------
-
- bool CDvdCore::StopFullScreen()
- {
- DbgLog((LOG_TRACE, 5, TEXT("CDvdCore::StopFullScreen()"))) ;
-
- if (NULL == m_pIVW)
- {
- DbgLog((LOG_ERROR, 0,
- TEXT("CDvdCore::StopFullScreen() -- no IVideoWindow pointer yet"))) ;
- return false ;
- }
-
- HRESULT hr ;
-
- // restore the window's position
- RECT rect;
- GetClientRect(m_hWnd, &rect);
- hr = m_pIVW->SetWindowPosition(0, 0, rect.right, rect.bottom);
- ASSERT(SUCCEEDED(hr)) ;
-
- // make it a child window again
- hr = m_pIVW->put_Owner(reinterpret_cast<OAHWND>(m_hWnd)) ;
- ASSERT(SUCCEEDED(hr)) ;
-
- // restore the window's styles
- hr = m_pIVW->put_WindowStyle(m_lOrigStyle) ; // restore the styles
- ASSERT(SUCCEEDED(hr)) ;
- hr = m_pIVW->put_WindowStyleEx(m_lOrigStyleEx) ; // restore the extended styles
- ASSERT(SUCCEEDED(hr)) ;
-
- KillTimer(m_hWnd, MOUSETIMER); // remove the mouse blanking timer
- ShowMouseCursor(true) ; // make sure to show mouse now
-
- m_bFullScreenOn = false;
-
- return true ;
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::OnDvdEvent()
- // Desc: This method receives DVD messages from our WndProc and acts on them
- //------------------------------------------------------------------------------
- LRESULT CDvdCore::OnDvdEvent(UINT uMessage, WPARAM wParam, LPARAM lParam)
- {
- DbgLog((LOG_TRACE, 5, TEXT("CDvdCore::OnDvdEvent()"))) ;
-
- long lEvent, lParam1, lParam2;
- long lTimeOut = 0;
-
- while (SUCCEEDED(m_pIME->GetEvent(&lEvent, &lParam1, &lParam2, lTimeOut)))
- {
- DbgLog((LOG_TRACE, 5, TEXT("Event: %#x"), lEvent)) ;
-
- HRESULT hr;
- switch(lEvent)
- {
-
- case EC_DVD_CURRENT_HMSF_TIME:
- {
- DVD_HMSF_TIMECODE * pTC = reinterpret_cast<DVD_HMSF_TIMECODE *>(&lParam1);
- m_CurTime = *pTC;
- m_pCallback->UpdateStatus(); // inform our client that something changed
- }
- break;
-
- case EC_DVD_CHAPTER_START:
- m_ulCurChapter = lParam1;
- break;
-
- case EC_DVD_TITLE_CHANGE:
- m_ulCurTitle = lParam1;
- break;
-
- case EC_DVD_NO_FP_PGC:
- hr = m_pIDvdC2->PlayTitle(1, DVD_CMD_FLAG_None, NULL);
- ASSERT(SUCCEEDED(hr));
- break;
-
- case EC_DVD_DOMAIN_CHANGE:
- 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
- DbgLog((LOG_TRACE, 3, TEXT("DVD Event: Domain changed to VMGM(2)/VTSM(3) (%ld)"), lParam1)) ;
- //PostMessage(m_hWnd, WM_COMMAND, IDM_USER_MENUSTATUS, (LPARAM) 1) ;
- m_bMenuOn = true; // now menu is "On"
- break ;
-
- case DVD_DOMAIN_Title: // = 4
- // Inform the app to update the menu option to show "Menu" again
- DbgLog((LOG_TRACE, 3, TEXT("DVD Event: Title Domain (%ld)"), lParam1)) ;
- //PostMessage(m_hWnd, WM_COMMAND, IDM_USER_MENUSTATUS, (LPARAM) 0) ;
- m_bMenuOn = false ; // we are no longer in a menu
- break ;
- } // end of domain change switch
- break;
-
-
- case EC_DVD_PARENTAL_LEVEL_CHANGE:
- if (IDYES == MessageBox(m_hWnd, TEXT("Accept Parental Level Change Request?"),
- TEXT("Accept Change?"), MB_YESNO))
- {
- m_pIDvdC2->AcceptParentalLevelChange(TRUE);
- }
- else
- {
- m_pIDvdC2->AcceptParentalLevelChange(FALSE);
- }
- break;
-
- case EC_DVD_ERROR:
- DbgLog((LOG_TRACE, 3, TEXT("DVD Event: Error event received (code %ld)"), lParam1)) ;
- switch (lParam1)
- {
- case DVD_ERROR_Unexpected:
- MessageBox(m_hWnd,
- TEXT("An unexpected error (possibly incorrectly authored content)")
- TEXT("\nwas encountered.")
- TEXT("\nCan't playback this DVD-Video disc."),
- TEXT("Error"), MB_OK | MB_ICONINFORMATION) ;
- m_pIMC->Stop() ;
- break ;
-
- case DVD_ERROR_CopyProtectFail:
- MessageBox(m_hWnd,
- TEXT("Key exchange for DVD copy protection failed.")
- TEXT("\nCan't playback this DVD-Video disc."),
- TEXT("Error"), MB_OK | MB_ICONINFORMATION) ;
- m_pIMC->Stop() ;
- break ;
-
- case DVD_ERROR_InvalidDVD1_0Disc:
- MessageBox(m_hWnd,
- TEXT("This DVD-Video disc is incorrectly authored for v1.0 of the spec.")
- TEXT("\nCan't playback this disc."),
- TEXT("Error"), MB_OK | MB_ICONINFORMATION) ;
- m_pIMC->Stop() ;
- break ;
-
- case DVD_ERROR_InvalidDiscRegion:
- MessageBox(m_hWnd,
- TEXT("This DVD-Video disc cannot be played, because it is not")
- TEXT("\nauthored to play in the current system region.")
- TEXT("\nThe region mismatch may be fixed by changing the")
- TEXT("\nsystem region (with DVDRgn.exe)."),
- TEXT("Error"), MB_OK | MB_ICONINFORMATION) ;
- m_pIMC->Stop() ;
- ChangeDvdRegion();
- break ;
-
- case DVD_ERROR_LowParentalLevel:
- MessageBox(m_hWnd,
- TEXT("Player parental level is set lower than the lowest parental")
- TEXT("\nlevel available in this DVD-Video content.")
- TEXT("\nCannot playback this DVD-Video disc."),
- TEXT("Error"), MB_OK | MB_ICONINFORMATION) ;
- m_pIMC->Stop() ;
- break ;
-
- case DVD_ERROR_MacrovisionFail:
- MessageBox(m_hWnd,
- TEXT("This DVD-Video content is protected by Macrovision.")
- TEXT("\nThe system does not satisfy Macrovision requirement.")
- TEXT("\nCan't continue playing this disc."),
- TEXT("Error"), MB_OK | MB_ICONINFORMATION) ;
- m_pIMC->Stop() ;
- break ;
-
- case DVD_ERROR_IncompatibleSystemAndDecoderRegions:
- MessageBox(m_hWnd,
- TEXT("No DVD-Video disc can be played on this system, because ")
- TEXT("\nthe system region does not match the decoder region.")
- TEXT("\nPlease contact the manufacturer of this system."),
- TEXT("Error"), MB_OK | MB_ICONINFORMATION) ;
- m_pIMC->Stop() ;
- break ;
-
- case DVD_ERROR_IncompatibleDiscAndDecoderRegions:
- MessageBox(m_hWnd,
- TEXT("This DVD-Video disc cannot be played on this system, because it is")
- TEXT("\nnot authored to be played in the installed decoder's region."),
- TEXT("Error"), MB_OK | MB_ICONINFORMATION) ;
- m_pIMC->Stop() ;
- break ;
- } // end of switch (lParam1)
- break ;
-
- // Next is warning
- case EC_DVD_WARNING:
- switch (lParam1)
- {
- case DVD_WARNING_InvalidDVD1_0Disc:
- DbgLog((LOG_ERROR, 1, TEXT("DVD Warning: Current disc is not v1.0 spec compliant"))) ;
- break ;
-
- case DVD_WARNING_FormatNotSupported:
- DbgLog((LOG_ERROR, 1, TEXT("DVD Warning: The decoder does not support the new format."))) ;
- break ;
-
- case DVD_WARNING_IllegalNavCommand:
- DbgLog((LOG_ERROR, 1, TEXT("DVD Warning: An illegal navigation command was encountered."))) ;
- break ;
-
- case DVD_WARNING_Open:
- DbgLog((LOG_ERROR, 1, TEXT("DVD Warning: Could not open a file on the DVD disc."))) ;
- MessageBox(m_hWnd,
- TEXT("A file on the DVD disc could not be opened. Playback may not continue."),
- TEXT("Warning"), MB_OK | MB_ICONINFORMATION) ;
- break ;
-
- case DVD_WARNING_Seek:
- DbgLog((LOG_ERROR, 1, TEXT("DVD Warning: Could not seek in a file on the DVD disc."))) ;
- MessageBox(m_hWnd,
- TEXT("Could not move to a different part of a file on the DVD disc. Playback may not continue."),
- TEXT("Warning"), MB_OK | MB_ICONINFORMATION) ;
- break ;
-
- case DVD_WARNING_Read:
- DbgLog((LOG_ERROR, 1, TEXT("DVD Warning: Could not read a file on the DVD disc."))) ;
- MessageBox(m_hWnd,
- TEXT("Could not read part of a file on the DVD disc. Playback may not continue."),
- TEXT("Warning"), MB_OK | MB_ICONINFORMATION) ;
- break ;
-
- default:
- DbgLog((LOG_ERROR, 1, TEXT("DVD Warning: An unknown (%ld) warning received."), lParam1)) ;
- break ;
- }
- break ;
-
- case EC_DVD_BUTTON_CHANGE:
- break;
-
- case EC_DVD_STILL_ON:
- if (TRUE == lParam1) // if there is a still without buttons, we can call StillOff
- m_bStillOn = true;
- break;
-
- case EC_DVD_STILL_OFF:
- m_bStillOn = false; // we are no longer in a still
- break;
-
- } // end of switch(lEvent)
- m_pIME->FreeEventParams(lEvent, lParam1, lParam2) ;
- } // end of while(GetEvent())
-
- return 0;
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::OnMouseEvent()
- // Desc: This method acts on mouse events sent to it from the WndProc method
- //------------------------------------------------------------------------------
-
- LRESULT CDvdCore::OnMouseEvent(UINT uMessage, WPARAM wParam, LPARAM lParam)
- {
- if (true == m_bFullScreenOn) // if any mouse activity happens while in full screen mode
- {
- ShowMouseCursor(true);
- }
-
- switch (uMessage)
- {
- case WM_MOUSEMOVE:
- {
- POINT pt;
- pt.x = GET_X_LPARAM(lParam);
- pt.y = GET_Y_LPARAM(lParam);
- m_pIDvdC2->SelectAtPosition(pt);
- return 0;
- }
-
- case WM_LBUTTONUP:
- {
- POINT pt;
- pt.x = GET_X_LPARAM(lParam);
- pt.y = GET_Y_LPARAM(lParam);
- m_pIDvdC2->ActivateAtPosition(pt);
- return 0;
- }
- }
- return DefWindowProc(m_hWnd, uMessage, wParam, lParam);
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::OnKeyEvent()
- // Desc: This method processes keyboard events forwarded to it by the WndProc.
- //------------------------------------------------------------------------------
-
- LRESULT CDvdCore::OnKeyEvent(WPARAM wParam, LPARAM lParam)
- {
- DbgLog((LOG_TRACE, 5, TEXT("CDvdCore::OnKeyEvent()"))) ;
-
- switch (wParam)
- {
- case VK_ESCAPE: // exit full screen
- if (true == m_bFullScreenOn) // only do this if we are in fullscreen mode
- StopFullScreen();
- return 0;
-
- case VK_RETURN: // activate the currently selected button
- m_pIDvdC2->ActivateButton();
- return 0;
-
- case VK_LEFT: // select the left button
- m_pIDvdC2->SelectRelativeButton(DVD_Relative_Left);
- return 0;
-
- case VK_RIGHT: // select the right button
- m_pIDvdC2->SelectRelativeButton(DVD_Relative_Right);
- return 0;
-
- case VK_UP: // select the upper button
- m_pIDvdC2->SelectRelativeButton(DVD_Relative_Upper);
- return 0;
-
- case VK_DOWN: // select the lower button
- m_pIDvdC2->SelectRelativeButton(DVD_Relative_Lower);
- return 0;
- }
- return DefWindowProc(m_hWnd, WM_KEYUP, wParam, lParam);
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::ShowMouseCursor()
- // Desc: This method is used to show or hide the cursor during fullscreen mode
- //------------------------------------------------------------------------------
-
- void CDvdCore::ShowMouseCursor(bool bShow)
- {
- DbgLog((LOG_TRACE, 5, TEXT("CDvdCore::ShowMouseCursor(%s)"), bShow ? TEXT("true") :
- TEXT("false"))) ;
-
- if (true == bShow) // display cursor
- {
- while (m_iMouseShowCount < 0)
- {
- m_iMouseShowCount = ::ShowCursor(TRUE) ; // keep adding until the count is 0 or higher
- }
- m_dwMouseMoveTime = timeGetTime() ; // it has just been moved
- }
- else // hide cursor
- {
- while (m_iMouseShowCount >= 0)
- {
- m_iMouseShowCount = ::ShowCursor(FALSE) ; // keep subtracting until the count is below 0
- }
- }
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::OnMouseTimer()
- // Desc: This method will hide the pointer if the mouse hasn't moved for
- // MOUSE_TIMEOUT milliseconds.
- //------------------------------------------------------------------------------
-
- LRESULT CDvdCore::OnMouseTimer(WPARAM wParam, LPARAM lParam)
- {
- DbgLog((LOG_TRACE, 5, TEXT("CDvdCore::OnMouseTimer()"))) ;
-
- if (MOUSETIMER != wParam ) // if it isn't our timer we won't do anything with it
- return (DefWindowProc(m_hWnd, WM_TIMER, wParam, lParam));
-
- // If we are in fullscreen mode, check if mouse should be hidden now
- if (true == m_bFullScreenOn) // we should be but just to make sure
- {
- if (timeGetTime() - m_dwMouseMoveTime > MOUSE_TIMEOUT)
- {
- ShowMouseCursor(false) ;
- }
- }
-
- return 0 ;
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::OnSize()
- // Desc: This method is called whenever we receive WM_SIZE. It will resize the
- // IVideoWindow window to match our new client space.
- //------------------------------------------------------------------------------
-
- LRESULT CDvdCore::OnSize(WPARAM wParam, LPARAM lParam)
- {
- DbgLog((LOG_TRACE, 5, TEXT("CDvdCore::OnSize()"))) ;
-
- // set the video window to fill the client space
- RECT rect;
- GetClientRect(m_hWnd, &rect);
- HRESULT hr = m_pIVW->SetWindowPosition(0, 0, rect.right, rect.bottom);
- ASSERT(SUCCEEDED(hr)) ;
- return 0;
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::GetParentalLevel()
- // Desc: This method returns the current parental level setting of the DVD Navigator
- //------------------------------------------------------------------------------
-
- ULONG CDvdCore::GetParentalLevel()
- {
- DbgLog((LOG_TRACE, 5, TEXT("CDvdCore::GetParentalLevel()"))) ;
-
- ULONG ulLevel = 0;
- UCHAR cCountry[2];
- HRESULT hr;
- hr = m_pIDvdI2->GetPlayerParentalLevel(&ulLevel, cCountry);
- ASSERT(SUCCEEDED(hr));
- return ulLevel;
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::SetParentalLevel()
- // Desc: This method sets the Navigator's parental level
- //------------------------------------------------------------------------------
-
- bool CDvdCore::SetParentalLevel(ULONG ulLevel)
- {
- DbgLog((LOG_TRACE, 5, TEXT("CDvdCore::SetParentalLevel() - Level: %u"), ulLevel)) ;
-
- if (Graph_Stopped2 != GetState())
- {
- // we need to be in the stop state to change parental levels.
- // we can either stop from IMediaControl or stop from IDvdControl2
- // we choose to stop from the IMediaControl because it makes the play code more clean
- m_pIDvdC2->SetOption(DVD_ResetOnStop, TRUE); // do a complete reset
- m_pIMC->Stop(); // stop the entire graph
- m_pIDvdC2->SetOption(DVD_ResetOnStop, FALSE); // restore previous settings
- SetState(Graph_Stopped2);
- }
-
- HRESULT hr = m_pIDvdC2->SelectParentalLevel(ulLevel);
- if (SUCCEEDED(hr))
- return true;
- else
- return false;
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::UpdateStatus()
- // Desc: This method is just a stub to make our work with the callback cleaner.
- // We will point our m_pCallback to this unless given a different pointer by
- // the calling function
- //------------------------------------------------------------------------------
-
- void CDvdCore::UpdateStatus(void)
- {
- //intentionally left blank
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::SetDirectory()
- // Desc: This method is a wrapper for SetDVDDirectory. It changes the current
- // directory used for video playback. It is called by the Select Disc
- // menu function.
- //------------------------------------------------------------------------------
-
- bool CDvdCore::SetDirectory(TCHAR *szDirectory)
- {
- DbgLog((LOG_TRACE, 5, TEXT("CDvdCore::SetDirectory()"))) ;
-
- HRESULT hr = m_pIDvdC2->Stop() ; // first ask player to stop the playback.
- if (SUCCEEDED(hr))
- SetState(Nav_Stopped);
-
- // Convert TCHAR filename to WCHAR for COM
- WCHAR szwFileName[MAX_PATH] ;
- #ifdef UNICODE
- lstrcpy(szwFileName, szDirectory) ;
- #else
- MultiByteToWideChar(CP_ACP, 0, szDirectory, -1, szwFileName, MAX_PATH) ;
- #endif // UNICODE
- hr = m_pIDvdC2->SetDVDDirectory(szwFileName) ;
- if (SUCCEEDED(hr)) // if the new file name is valid DVD-video volume
- {
- return true;
- }
- else
- {
- DbgLog((LOG_ERROR, 2, TEXT("WARNING: SetDVDDirectory(%s) failed (Error 0x%lx)"),
- szDirectory, hr)) ;
- return false;
- }
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::FrameStep()
- // Desc: This method will pause the graph and step forward one step at a time
- //------------------------------------------------------------------------------
-
- bool CDvdCore::FrameStep()
- {
- DbgLog((LOG_TRACE, 5, TEXT("CDvdCore::FrameStep()"))) ;
-
- if (Uninitialized == GetState())
- {
- DbgLog((LOG_ERROR, 2, TEXT("WARNING: DVDCore is not initialized!"),
- szDirectory, hr)) ;
- return false;
- }
-
- // Get the Frame Stepping Interface
- IVideoFrameStep* pFS;
- HRESULT hr;
- hr = m_pGraph->QueryInterface(__uuidof(IVideoFrameStep), (PVOID *)&pFS);
-
- if (FAILED(hr))
- {
- DbgLog((LOG_ERROR, 2, TEXT("WARNING: Can't get IVideoFrameStep interface!"),
- szDirectory, hr)) ;
- return false;
- }
-
- // check if this decoder can step
- hr = pFS->CanStep(0L, NULL);
-
- if (S_FALSE == hr)
- {
- DbgLog((LOG_ERROR, 2, TEXT("WARNING: Decoder can't step"),
- szDirectory, hr)) ;
- pFS->Release();
- return false;
- }
-
- // this will only work while the graph is paused
- m_pIMC->Pause();
- SetState(Graph_Paused);
-
- // step one frame
- hr = pFS->Step(1, NULL);
-
- bool retVal = SUCCEEDED(hr) ? true : false;
-
- // clean up after ourselves
- pFS->Release();
-
- return retVal;
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::PlayChapter()
- // Desc: This method plays a chapter in the current title
- //------------------------------------------------------------------------------
-
- bool CDvdCore::PlayChapter(ULONG ulChap)
- {
- DbgLog((LOG_TRACE, 5, TEXT("CDvdCore::PlayChapter() %u"), ulChap)) ;
-
- HRESULT hr = m_pIDvdC2->PlayChapter(ulChap, DVD_CMD_FLAG_Block, NULL);
- if (SUCCEEDED(hr))
- return true;
- else
- {
- if (VFW_E_DVD_OPERATION_INHIBITED == hr)
- m_pCallback->Prohibited();
- DbgLog((LOG_ERROR, 1, TEXT("CDvdCore::PlayChapter() failed: %#x"), hr)) ;
- return false;
- }
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::PlayChapterInTitle()
- // Desc: This method plays a chapter in the specified title
- //------------------------------------------------------------------------------
-
- bool CDvdCore::PlayChapterInTitle(ULONG ulTitle, ULONG ulChapter)
- {
- DbgLog((LOG_TRACE, 5, TEXT("CDvdCore::PlayChapterInTitle() Title: %u, "
- "Chapter: %u"), ulTitle, ulChapter)) ;
-
- HRESULT hr = m_pIDvdC2->PlayChapterInTitle(ulTitle, ulChapter, DVD_CMD_FLAG_Block, NULL);
- if (SUCCEEDED(hr))
- return true;
- else
- {
- if (VFW_E_DVD_OPERATION_INHIBITED == hr)
- m_pCallback->Prohibited();
- DbgLog((LOG_ERROR, 1, TEXT("CDvdCore::PlayChapterInTitle() failed: %#x"), hr)) ;
- return false;
- }
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::PlayTime()
- // Desc: This method plays a time in the current title
- //------------------------------------------------------------------------------
-
- bool CDvdCore::PlayTime(DVD_HMSF_TIMECODE time)
- {
- DbgLog((LOG_TRACE, 5, TEXT("CDvdCore::PlayTime() hh:mm:ss %u:%u:%u"),
- time.bHours, time.bMinutes, time.bSeconds)) ;
-
- /*
- time.bFrames = 1;
-
- DVD_HMSF_TIMECODE tempTime;
- tempTime.bHours = 0;
- tempTime.bMinutes = 5;
- tempTime.bSeconds = 5;
- tempTime.bFrames = 1;
- */
-
- HRESULT hr = m_pIDvdC2->PlayAtTime(&time, DVD_CMD_FLAG_Block, NULL);
- if (SUCCEEDED(hr))
- return true;
- else
- {
- DbgLog((LOG_ERROR, 1, TEXT("CDvdCore::PlayTime() failed: %#x"), hr)) ;
- return false;
- }
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::ChangeDvdRegion()
- // Desc: This method changes the DVD Region
- //
- // Returns:
- // true: if the drive region change is successful
- // false: if drive region change fails (probably
- // because no drive was found with a valid
- // DVD-V disc).
- //
- //------------------------------------------------------------------------------
-
- bool CDvdCore::ChangeDvdRegion()
- {
- typedef BOOL (APIENTRY * DVDPPLAUNCHER) (HWND hWnd, CHAR DriveLetter);
-
- bool bRegionChanged = false;
- TCHAR szCmdLine[MAX_PATH];
-
- //
- // First find out which drive is a DVD drive with a
- // valid DVD-V disc.
- //
- TCHAR szDVDDrive[4];
- if (! GetDriveLetter (szDVDDrive) )
- {
- DbgLog((LOG_ERROR, 1, TEXT("No DVD drive was found with DVD-Video disc.")
- TEXT("Cannot change DVD region of the drive.")));
- return false;
- }
-
- //
- // Detect which OS we are running on. For Windows NT,
- // use the storprop.dll, while for Windows 9x platform
- // use the DVDRgn.exe application to change the region.
- //
- OSVERSIONINFO ver;
- ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- GetVersionEx(&ver);
- if (VER_PLATFORM_WIN32_NT == ver.dwPlatformId)
- {
- // Windows NT platform
- HINSTANCE hInstDLL;
- DVDPPLAUNCHER dvdPPLauncher;
- CHAR szDVDDriveA[4];
-
- #ifdef UNICODE
- WideCharToMultiByte(0, 0, szDVDDrive, -1,
- szDVDDriveA, sizeof(szDVDDriveA),
- NULL, NULL );
- #else
- strcpy(szDVDDriveA, szDVDDrive);
- #endif // UNICODE
-
- GetSystemDirectory(szCmdLine, MAX_PATH);
- lstrcat(szCmdLine, TEXT("\\storprop.dll"));
-
- hInstDLL = LoadLibrary (szCmdLine);
- if (hInstDLL)
- {
- dvdPPLauncher = (DVDPPLAUNCHER) GetProcAddress(hInstDLL, "DvdLauncher");
- if (dvdPPLauncher)
- {
- if (TRUE == dvdPPLauncher(m_hWnd, szDVDDriveA[0]))
- bRegionChanged = true;
- else
- bRegionChanged = false;
- }
-
- FreeLibrary(hInstDLL);
- }
- } // end of region change code for Windows NT platform
- else // Windows 98 platform
- {
- // Get path of \windows\dvdrgn.exe for command line
- // string
- GetWindowsDirectory(szCmdLine, MAX_PATH);
- lstrcat(szCmdLine, TEXT("\\DVDRgn.exe "));
-
- // Add only the drive letter as command line parameter
- _tcsncat(szCmdLine, szDVDDrive, 1);
-
- // Prepare to execute DVDRgn.exe
- STARTUPINFO StartupInfo;
- PROCESS_INFORMATION ProcessInfo;
- StartupInfo.cb = sizeof(StartupInfo);
- StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
- StartupInfo.wShowWindow = SW_SHOWNORMAL;
- StartupInfo.lpReserved = NULL;
- StartupInfo.lpDesktop = NULL;
- StartupInfo.lpTitle = NULL;
- StartupInfo.cbReserved2 = 0;
- StartupInfo.lpReserved2 = NULL;
- if (CreateProcess(NULL, szCmdLine, NULL, NULL, TRUE,
- NORMAL_PRIORITY_CLASS, NULL, NULL, &StartupInfo, &ProcessInfo) )
- {
- // Wait until DVDRgn.exe finishes
- WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
- DWORD dwRet = 1;
- BOOL bRet = GetExitCodeProcess(ProcessInfo.hProcess,
- &dwRet);
- // If the user changed the drive region
- // successfully, the exit code of DVDRgn.exe is 0.
- if (bRet && 0 == dwRet)
- {
- bRegionChanged = true;
- }
- }
- } // end of region change code for Windows 9x platform
-
- if (bRegionChanged) // if region changed successfully
- {
- // We now cycle through stop. We have to turn on ResetOnStop or we won't reset
- // the internals of the navigator when we stop. After we have stopped, we reset
- // this option to its original state.
- HRESULT hr;
- hr = m_pIMC->Pause();
- hr = m_pIDvdC2->SetOption(DVD_ResetOnStop, TRUE);
- hr = m_pIMC->Stop(); // come to a complete stop.
- hr = m_pIDvdC2->SetOption(DVD_ResetOnStop, FALSE);
- hr = m_pIMC->Run();
- return true;
- }
- else // DVD region didn't happen
- {
- DbgLog((LOG_ERROR, 1, TEXT("DVD drive region could not be changed.")) );
- return false;
- }
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::GetDriveLetter()
- // Desc: This method gets the drive letter of the currently active DVD drive
- //
- // Returns:
- // true: if a DVD drive is found (with valid disc)
- // false: if no DVD drive was found with valid DVD-V
- // disc.
- //
- //------------------------------------------------------------------------------
-
- bool CDvdCore::GetDriveLetter(TCHAR *pszDrive)
- {
- WCHAR szwPath[MAX_PATH];
- ULONG ulActualSize;
-
- pszDrive[0] = pszDrive[3] = 0;
- //
- // Get the current root directory
- //
- if (SUCCEEDED(m_pIDvdI2->GetDVDDirectory(szwPath, MAX_PATH, &ulActualSize)))
- {
- #ifdef UNICODE
- lstrcpynW(pszDrive, szwPath, 3);
- #else
- CHAR szDrive[MAX_PATH];
- WideCharToMultiByte(CP_ACP, NULL, szwPath, -1, szDrive, MAX_PATH, NULL, NULL);
- lstrcpyn(pszDrive, szDrive, 3);
- #endif;
- return true;
- }
- return false; // couldn't find a directory
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::DoesFileExist()
- // Desc: This method determines if the given filename is an existing file
- //------------------------------------------------------------------------------
-
- bool CDvdCore::DoesFileExist(PTSTR pszFile)
- {
- HANDLE hFile = NULL ;
- //
- // We don't want any error message box to pop up when
- // we try to test if the required file is available to
- // open for read.
- //
- UINT uErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS |
- SEM_NOOPENFILEERRORBOX);
- hFile = CreateFile(pszFile, GENERIC_READ,
- FILE_SHARE_READ, NULL,
- OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN,
- NULL);
- SetErrorMode(uErrorMode); // restore error mode
- if (INVALID_HANDLE_VALUE == hFile)
- return FALSE ;
-
- CloseHandle(hFile);
- return TRUE;
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::UnInitMessageSink()
- // Desc: This method undoes what InitMessageSink does. It is important that we remove
- // the child window bit from the video window before we close the parent window.
- //------------------------------------------------------------------------------
-
- void CDvdCore::UnInitMessageSink()
- {
- // Make the sure the video window is no longer child of the playback window.
- if (m_pIVW)
- {
- long lStyle;
- m_pIVW->get_WindowStyle(&lStyle);
- m_pIVW->put_WindowStyle(lStyle & ~WS_CHILD);
- m_pIVW->put_Owner(NULL);
- }
- DestroyWindow(m_hWnd);
-
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::OnClose()
- // Desc: This method is called when the playback window is closed. In response it
- // calls the currently registered IDvdCallback object's Exit method.
- //------------------------------------------------------------------------------
-
- LRESULT CDvdCore::OnClose()
- {
- m_pCallback->Exit();
- return 0;
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::GetPlaybackWindowRect()
- // Desc: This method will check the size of the desktop and scale the size of
- // the playback window's accordingly.
- //------------------------------------------------------------------------------
-
- RECT CDvdCore::GetPlaybackWindowRect()
- {
- RECT rDesktop, rWindow, rApp;
- SystemParametersInfo(SPI_GETWORKAREA, NULL, &rDesktop, NULL);
- rApp = m_pCallback->GetAppWindow();
-
- rWindow.left = rDesktop.left + 5; // leave a 5 pixel gap
- rWindow.top = rDesktop.top + 5; // leave a 5 pixel gap
- rWindow.bottom = rApp.top; // place this window above the top of player window
- rWindow.right = rDesktop.left + ((rWindow.bottom - rWindow.top) * 4)/3; //maintain 4:3 aspect ratio
- return rWindow;
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::GetDvdText()
- // Desc: This method will read the Dvd Text Info off of a disc and output it to
- // a messagebox. We will be using GetDvdTextStringAsUnicode. There is
- // also a "native" version but we don't use it here. The Unicode version
- // will work better with non-English text.
- //
- // This is done only to show how to read the text info and
- // display it. In a real application, you would probably
- // create your own data structure to hold the text information.
- //------------------------------------------------------------------------------
-
- bool CDvdCore::GetDvdText()
- {
- ULONG ulNumStrings, ulNumLang;
- LCID LangCode;
- DVD_TextCharSet CharSet;
-
- HRESULT hr;
-
- // first, we check if there is any text on this disc
- hr = m_pIDvdI2->GetDVDTextNumberOfLanguages(&ulNumLang);
- if (0 == ulNumLang || FAILED(hr))
- {
- MessageBox(m_hWnd, TEXT("There is no text on this disc"), TEXT("No Text Present"),
- MB_OK);
- return false;
- }
-
- ULONG ulLangIndex = 0; // We will just grab the first language. You might want to
- //ask the user which language they want to see or try to
- //choose one that closest matches the locale of the machine
-
- // next we get the number of strings available
- hr = m_pIDvdI2->GetDVDTextLanguageInfo(ulLangIndex,
- &ulNumStrings, &LangCode, &CharSet);
-
- if (FAILED(hr))
- {
- MessageBox(m_hWnd, TEXT("There was an error getting the number of Strings"),
- TEXT("Error!"), MB_OK);
- return false;
- }
-
- #ifdef UNICODE
- wstringstream aString;
- #else
- stringstream aString;
- #endif
-
- WCHAR buffer[1024] = {L"\0"}; // should be ample space
-
- for (ULONG ulStringIndex = 0; ulStringIndex < ulNumStrings; ulStringIndex++)
- {
-
- ULONG ulActualSize;
- DVD_TextStringType type;
-
- hr = m_pIDvdI2->GetDVDTextStringAsUnicode(ulLangIndex,
- ulStringIndex, buffer, sizeof(buffer)/sizeof(*buffer), &ulActualSize, &type);
-
- if (SUCCEEDED(hr))
- {
- #ifdef UNICODE
-
- // Any string type less than 0x20 is an empty string used
- // only to identify the logical structure or stream.
- // Here, we display the string types to illustrate how
- // they are used to organize text strings on the disc.
- if(type > DVD_Channel_Audio) //0x20
- aString << AsStr << buffer << endl;
- else
- aString << AsStr << endl;
- #else
- // we need to convert the Unicode to ANSI so we can output it
- // stringstream can't handle unicode characters
- CHAR myBuffer[1024];
- WideCharToMultiByte(CP_ACP, 0, buffer, -1, myBuffer, 1024, NULL, NULL);
-
- // Any string type less than 0x20 is an empty string used
- // only to identify the logical structure or stream.
- // Here, we display the string types to illustrate how
- // they are used to organize text strings on the disc.
- if(type > DVD_Channel_Audio) //0x20
- aString << AsStr(type) << " " << myBuffer << endl;
- else
- aString << AsStr(type) << " " << endl;
- #endif
- }
- }
-
- MessageBox(m_hWnd, aString.str().c_str(), TEXT("Dvd Text Info"), MB_OK);
- return true; // once everything is over, if we haven't failed, we must have passed
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::GetAudioAttributes()
- // Desc: This method will parse the audio attributes of the current audio stream
- // and output it to a messagebox.
- //
- // You probably don't want to dump raw data like this on the user. This is
- // merely to demonstrate how to parse the information. The same information
- // found here can be used to describe the audio in a more user-friendly
- // manner. In a real application, this function should probably return
- // a string to CApp rather than displaying it itself.
- //------------------------------------------------------------------------------
-
- bool CDvdCore::GetAudioAttributes()
- {
- HRESULT hr;
-
- DVD_AudioAttributes audioAtr;
- hr = m_pIDvdI2->GetAudioAttributes(DVD_STREAM_DATA_CURRENT, &audioAtr);
-
- if (FAILED(hr))
- {
- MessageBox(m_hWnd, TEXT("GetAudioAttributes Failed"), TEXT("Error!"), MB_OK);
- return false;
- }
-
- #ifdef UNICODE
- wstringstream aString;
- #else
- stringstream aString;
- #endif
-
- aString << TEXT("Audio Attributes :") << endl << endl << TEXT("Audio Application Mode =")
- << AsStr(audioAtr.AppMode) << endl;
-
- aString << TEXT("Audio Format = ") << AsStr(audioAtr.AudioFormat) << endl;
-
- aString << TEXT("Multichannel Extension = ")
- << AsStr( audioAtr.fHasMultichannelInfo != FALSE ) << endl;
-
- aString << TEXT("Number of Audio Channels = ") <<
- static_cast<ULONG>(audioAtr.bNumberOfChannels) << endl; // the cast is only necessary to
- // allow IOStream to understand it
-
- aString << TEXT("Sampling Frequency = ") << audioAtr.dwFrequency << endl;
-
- aString << TEXT("Sampling Quantization = ") << static_cast<ULONG>(audioAtr.bQuantization) << endl;
-
- aString << TEXT("Language Code LCID = ") << audioAtr.Language << endl;
-
- aString << TEXT("Language Code Extension = ") << AsStr(audioAtr.LanguageExtension) << endl;
-
- if( DVD_AudioMode_Karaoke == audioAtr.AppMode )
- {
- DVD_KaraokeAttributes karaokeAtr;
- hr = m_pIDvdI2->GetKaraokeAttributes(DVD_STREAM_DATA_CURRENT, &karaokeAtr );
- if (SUCCEEDED(hr))
- {
- aString << endl << TEXT("Karaoke Attributes :") << endl << endl;
- aString << TEXT("Version = ") << static_cast<ULONG>(karaokeAtr.bVersion) << endl;
-
- aString << TEXT("MasterOfCeremoniesInGuideVocal1 = ") <<
- AsStr( karaokeAtr.fMasterOfCeremoniesInGuideVocal1 != FALSE ) << endl;
-
- aString << TEXT("Duet = ") << AsStr( karaokeAtr.fDuet != FALSE ) << endl;
-
- aString << TEXT("ChannelAssignment = ") << AsStr( karaokeAtr.ChannelAssignment ) << endl;
-
-
- if( VFW_S_DVD_CHANNEL_CONTENTS_NOT_AVAILABLE != hr)
- {
- aString << endl << TEXT("Channel contents:") << endl << endl;
- for( UINT i=0; i < audioAtr.bNumberOfChannels; i++)
- {
- aString << TEXT("Channel ") << i << TEXT(":");
- WORD c = karaokeAtr.wChannelContents[i];
- if( c & DVD_Karaoke_GuideVocal1 ) aString << TEXT(" GuideVocal1");
- if( c & DVD_Karaoke_GuideVocal2 ) aString << TEXT(" GuideVocal2");
- if( c & DVD_Karaoke_GuideMelody1 ) aString << TEXT(" GuideMelody1");
- if( c & DVD_Karaoke_GuideMelody2 ) aString << TEXT(" GuideMelody2");
- if( c & DVD_Karaoke_GuideMelodyA ) aString << TEXT(" GuideMelodyA");
- if( c & DVD_Karaoke_GuideMelodyB ) aString << TEXT(" GuideMelodyB");
- if( c & DVD_Karaoke_SoundEffectA ) aString << TEXT(" SoundEffectA");
- if( c & DVD_Karaoke_SoundEffectB ) aString << TEXT(" SoundEffectB");
- aString << endl;
- }
- }
- }
- }
- MessageBox(m_hWnd, aString.str().c_str(), TEXT("Audio Attributes"), MB_OK);
- return true;
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::GetVideoAttributes()
- // Desc: This method will parse the video attributes of the current video stream
- // and output it to a messagebox.
- //
- // You probably don't want to dump raw data like this on the user. This is
- // merely to demonstrate how to parse the information. The same information
- // found here can be used to describe the video in a more user-friendly
- // manner. In a real application, this function should probably return
- // a string to CApp rather than displaying it itself.
- //------------------------------------------------------------------------------
-
- bool CDvdCore::GetVideoAttributes()
- {
- DVD_VideoAttributes atrVideo;
- HRESULT hr;
- hr = m_pIDvdI2->GetCurrentVideoAttributes(&atrVideo);
- if (FAILED(hr))
- {
- MessageBox(m_hWnd, TEXT("GetCurrentVideoAttributes Failed"), TEXT("Error!"), MB_OK);
- return false;
- }
-
- #ifdef UNICODE
- wstringstream aString;
- #else
- stringstream aString;
- #endif
-
- aString << TEXT("Video Attributes:") << endl << endl;
-
- aString << TEXT("Pan-Scan permitted: ") << AsStr(atrVideo.fPanscanPermitted) << endl;
-
- aString << TEXT("Letterbox permitted: ") << AsStr(atrVideo.fLetterboxPermitted) << endl;
-
- aString << TEXT("Aspect: " << atrVideo.ulAspectX << TEXT(" x ") << atrVideo.ulAspectY << endl;
-
- aString << TEXT("Frame Rate: ") << atrVideo.ulFrameRate << endl;
-
- aString << TEXT("Frame Height: ") << atrVideo.ulFrameHeight << endl;
-
- aString << TEXT("Compression Mode: ") << AsStr(atrVideo.Compression) << endl;
-
- aString << TEXT("Line21 Field 1: ") << AsStr(atrVideo.fLine21Field1InGOP) << endl;
-
- aString << TEXT("Line21 Field 2: ") << AsStr(atrVideo.fLine21Field2InGOP) << endl;
-
- aString << TEXT("Source Resolution: ") << atrVideo.ulSourceResolutionX << TEXT(" x ") <<
- atrVideo.ulSourceResolutionY) << endl;
-
- aString << TEXT("Is Source Letterboxed? ") << AsStr(atrVideo.fIsSourceLetterboxed) << endl;
-
- aString << TEXT("Is Film Mode? ") << AsStr(atrVideo.fIsFilmMode) << endl;
-
- MessageBox(m_hWnd, aString.str().c_str(), TEXT("Video Attributes"), MB_OK);
- return true;
- }
-
-
- //------------------------------------------------------------------------------
- // Name: CDvdCore::GetSPAttributes()
- // Desc: This method will parse the subpicture attributes of the current video stream
- // and output it to a messagebox.
- //
- // You probably don't want to dump raw data like this on the user. This is
- // merely to demonstrate how to parse the information. The same information
- // found here can be used to describe the subpicture in a more user-friendly
- // manner. In a real application, this function should probably return
- // a string to CApp rather than displaying it itself.
- //------------------------------------------------------------------------------
-
- bool CDvdCore::GetSPAttributes()
- {
- DVD_SubpictureAttributes atrSP;
- HRESULT hr;
- hr = m_pIDvdI2->GetSubpictureAttributes(DVD_STREAM_DATA_CURRENT, &atrSP);
- if (FAILED(hr))
- {
- MessageBox(m_hWnd, TEXT("GetSubpictureAttributes Failed"), TEXT("Error!"), MB_OK);
- return false;
- }
-
- #ifdef UNICODE
- wstringstream aString;
- #else
- stringstream aString;
- #endif
-
- aString << TEXT("SubPicture Attributes:") << endl << endl;
- aString << TEXT("Subpicture Type = ") << AsStr(atrSP.Type) << endl;
-
- aString << TEXT("Subpicture Coding Mode = ") << AsStr(atrSP.CodingMode) << endl;
-
- TCHAR pszCode[100];
- if (0 == GetLocaleInfo(atrSP.Language, LOCALE_SLANGUAGE, pszCode, 100))
- {
- aString << TEXT("GetLocaleInfo Failed !!!") << endl;
- }
- else
- {
- aString << TEXT("Language Code = ") << pszCode << endl;
- }
-
- aString << TEXT("Language Code Extension = ") << AsStr(atrSP.LanguageExtension) << endl;
-
- MessageBox(m_hWnd, aString.str().c_str(), TEXT("Video Attributes"), MB_OK);
- return true;
- }
-
-
-