private:
TCHAR m_szAppName[50] ; // internal name of the app
TCHAR m_szAppTitle[50] ; // title bar text
HINSTANCE m_hInstance ;
HWND m_hWnd ;
HWND m_hwndToolBar ;
// Video window related
bool m_bFullScreenOn ;
RECT m_rectOrgVideo ; // used to store the original video rectangle during fullscreen playback
long m_lOrgStyle ; // original video window style bits (before fullscreen)
long m_lOrgStyleEx ; // original video window extended style bits (.....)
// Volume/Balance related
float m_fVolumePos; // Volume Position
float m_fBalancePos; // Balance Position
//------------------------------------------------------------------------------
// Type Definitions
//------------------------------------------------------------------------------
// Begin default media search at root directory
#define DEFAULT_MEDIA_PATH TEXT("\\\0")
//------------------------------------------------------------------------------
// Name: CMPlayer1App::CMPlayer1App()
// Desc: This is the constructor for CMPlayer1App. It sets default values and disables
// power saving.
//------------------------------------------------------------------------------
// Initialize COM
if (FAILED(CoInitialize(NULL)))
{
TRACE(TEXT("CoInitialize Failed!\r\n")) ;
exit(1) ;
}
// 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
//------------------------------------------------------------------------------
// Name: CMPlayer1App::~CMPlayer1App()
// Desc: This is the destructor for CMPlayer1App.
//------------------------------------------------------------------------------
CMPlayer1App::~CMPlayer1App()
{
if (m_pGB != NULL)
{
OnFileClose() ;
}
// Finished with COM
CoUninitialize() ;
// 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
//------------------------------------------------------------------------------
// Name: CMPlayer1App::SetAppValues()
// Desc: This method sets the basic application values like szAppName and hInstance
//------------------------------------------------------------------------------
void CMPlayer1App::SetAppValues(HINSTANCE hInst, PTSTR szAppName, int iAppTitleResId)
{
// The Windows stuff
m_hInstance = hInst ;
lstrcpy(m_szAppName, szAppName) ;
LoadString(m_hInstance, IDS_APP_TITLE, m_szAppTitle, 100) ;
}
//------------------------------------------------------------------------------
// Name: CMPlayer1App::InitInstance()
// Desc: This method registers and creates our window and toolbar.
//------------------------------------------------------------------------------
bool CMPlayer1App::InitInstance(int nCmdShow)
{
// 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 MPlayer1App 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 MPlayer1App 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;
}
if (0 == RegisterClassEx(&wc))
{
TRACE("ERROR: RegisterClassEx() for MPlayer1App class failed (Error %ld)\n", 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 center of the screen
m_hWnd = CreateWindowEx(0, m_szAppName, m_szAppTitle, WS_OVERLAPPEDWINDOW,
(rDesktop.right - rDesktop.left) / 2 - 150,
(rDesktop.bottom - rDesktop.top) / 2 - 80,
300, 160, NULL, NULL, m_hInstance, NULL) ;
if (! m_hWnd)
{
TRACE("ERROR: CreateWindowEx() failed (Error %ld)\n", 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) ;
// and finally, we make the window visible
ShowWindow(m_hWnd, nCmdShow) ;
UpdateWindow(m_hWnd) ;
return true ;
}
//------------------------------------------------------------------------------
// Name: CMPlayer1App::OnDraw()
// Desc: This method draws something on the screen
//------------------------------------------------------------------------------
void CMPlayer1App::OnDraw(HDC hDC)
{
// TODO: Place code here.
}
// Get the first output pin of the new source filter. Audio sources
// typically have only one output pin, so for most audio cases finding
// any output pin is sufficient.
// Get the first output pin of the new source filter. Audio sources
// typically have only one output pin, so for most audio cases finding
// any output pin is sufficient.
#define CONNECTPINS(x, y, z) \
{ \
if ((y != NULL) && (z != NULL)) \
{ \
IPin *pPin; \
z->ConnectedTo(&pPin); \
\
if (pPin == NULL) \
x->Connect(y, z); \
else \
pPin->Release(); \
} \
}
//------------------------------------------------------------------------------
// Name: CMPlayer1App::OnFileOpen()
// Desc: This method open a file dialog and render the selected file.
//------------------------------------------------------------------------------
#include "myuuids.h"
HRESULT CMPlayer1App::OnFileOpen()
{
HRESULT hr ;
if (m_pGB != NULL)
{
JIF(OnFileClose()) ;
}
// 미디어 파일 불러오기
// Open File Dialog ...
static OPENFILENAME ofn={0} ;
static BOOL bSetInitialDir = FALSE ;
// Clear open dialog remnants before calling RenderFile()
SetWindowText(m_hWnd, m_szFileName) ;
UpdateWindow(m_hWnd) ;
// Get the interface for DirectShow's GraphBuilder
JIF(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&m_pGB)) ;
// Render Pin ...
// Have the graph construct its the appropriate graph automatically
LIF(RenderFilter(m_pGB, pFilterFileSourceAsync));
/*
IBaseFilter *pSourceFilter ;
JIF(m_pGB->AddSourceFilter(wFileName, wFileName, &pSourceFilter)) ;
if (pSourceFilter != NULL)
{
LIF(RenderFilter(m_pGB, pSourceFilter)) ;
}
// Release a interface
SAFE_RELEASE(pSourceFilter) ;*/
/*
// Render File ...
// Have the graph construct its the appropriate graph automatically
JIF(m_pGB->RenderFile(wFileName, NULL)) ;
*/
// {
// Query for video interfaces
IVideoWindow * pVW ;
JIF(m_pGB->QueryInterface(IID_IVideoWindow, (void **)&pVW)) ;
if (pVW != NULL)
{
LIF(pVW->put_Owner((OAHWND)m_hWnd)) ;
LIF(pVW->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN)) ;
// resizing
LIF(OnSize());
}
// Release a interface
SAFE_RELEASE(pVW) ;
// }
// {
// Get the video size
IBasicVideo * pBV ;
JIF(m_pGB->QueryInterface(IID_IBasicVideo, (void **)&pBV)) ;
if (pBV != NULL)
{
long lWidth, lHeight ;
hr = pBV->GetVideoSize(&lWidth, &lHeight) ;
if (SUCCEEDED(hr))
{
// Track the movement of the container window and resize as needed
RECT rcToolbar ;
GetWindowRect(m_hwndToolBar, &rcToolbar) ;
int nToolbarHeight = rcToolbar.bottom - rcToolbar.top ;
SetWindowPos(m_hWnd, HWND_NOTOPMOST, 0, 0,
lWidth, lHeight + nToolbarHeight,
SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE) ;
}
}
// Release a interface
SAFE_RELEASE(pBV) ;
// }
// {
// Set the owner window to receive event notices
IMediaEventEx * pME ;
JIF(m_pGB->QueryInterface(IID_IMediaEventEx, (void **)&pME)) ;
if (pME != NULL)
{
LIF(pME->SetNotifyWindow((OAHWND)m_hWnd, WM_GRAPHNOTIFY, 0)) ;
}
// Release a interface
SAFE_RELEASE(pME) ;
// }
#ifdef REGISTER_FILTERGRAPH
hr = AddGraphToRot(m_pGB, &m_dwGraphRegister) ;
if (FAILED(hr))
{
TRACE(TEXT("Failed to register filter graph with ROT! hr=0x%x"), hr) ;
m_dwGraphRegister = 0 ;
}
#endif
return S_OK ;
}
//------------------------------------------------------------------------------
// Name: CMPlayer1App::OnFileClose()
// Desc: This method release the filter graph manager.
//------------------------------------------------------------------------------
HRESULT CMPlayer1App::OnFileClose()
{
if (m_pGB == NULL)
return E_ABORT ;
HRESULT hr ;
// Query for media control interfaces
IMediaControl * pMC ;
JIF(m_pGB->QueryInterface(IID_IMediaControl, (void **)&pMC)) ;
if (pMC != NULL)
{
// Stop the graph to stop the media file
LIF(pMC->Stop()) ;
}
// Release a interface
SAFE_RELEASE(pMC) ;
// {
// Query for media event interfaces
IMediaEventEx * pME;
JIF(m_pGB->QueryInterface(IID_IMediaEventEx, (void **)&pME));
if (pME != NULL)
{
// Relinquish ownership (IMPORTANT!)
LIF(pME->SetNotifyWindow(NULL, WM_GRAPHNOTIFY, 0));
}
// Release a interface
SAFE_RELEASE(pME);
// }
// {
// Query for video interfaces
IVideoWindow * pVW;
JIF(m_pGB->QueryInterface(IID_IVideoWindow, (void **)&pVW));
if (pVW != NULL)
{
// Relinquish ownership (IMPORTANT!) after hiding video window
LIF(pVW->put_Visible(OAFALSE));
LIF(pVW->put_Owner(NULL));
}
// Release a interface
SAFE_RELEASE(pVW);
// }
#ifdef REGISTER_FILTERGRAPH
if (m_dwGraphRegister)
{
RemoveGraphFromRot(m_dwGraphRegister) ;
m_dwGraphRegister = 0 ;
}
#endif
// Let's get ready to rumble!
ShowWindow(m_hWnd, SW_SHOW) ;
UpdateWindow(m_hWnd) ;
SetForegroundWindow(m_hWnd) ;
SetFocus(m_hWnd) ;
// Query for media control interfaces
IMediaControl * pMC ;
JIF(m_pGB->QueryInterface(IID_IMediaControl, (void **)&pMC)) ;
if (pMC != NULL)
{
// Run the graph to play the media file
LIF(pMC->Run()) ;
}
// Release a interface
SAFE_RELEASE(pMC) ;
// give a focus to the Video window, again!
SetFocus(m_hWnd) ;
// Query for media control interfaces
IMediaControl * pMC ;
JIF(m_pGB->QueryInterface(IID_IMediaControl, (void **)&pMC)) ;
if (pMC != NULL)
{
// Pause the graph to pause the media file
LIF(pMC->Pause()) ;
}
// Release a interface
SAFE_RELEASE(pMC) ;
return hr ;
}
HRESULT CMPlayer1App::OnStopClip()
{
HRESULT hr ;
if (m_pGB == NULL)
JIF(OnFileOpen()) ;
// Query for media control interfaces
IMediaControl * pMC ;
JIF(m_pGB->QueryInterface(IID_IMediaControl, (void **)&pMC)) ;
if (pMC != NULL)
{
// Stop the graph to stop the media file
LIF(pMC->Stop()) ;
}
// Query for media seeking interfaces
IMediaSeeking * pMS ;
JIF(m_pGB->QueryInterface(IID_IMediaSeeking, (void **)&pMS)) ;
if (pMS != NULL)
{
// Go to the previous of the graph, usually the very first.
LONGLONG pos = 0 ;
LIF(pMS->SetPositions(&pos, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning)) ;
// Display the first frame to indicate the reset condition
LIF(pMC->Pause()) ;
}
// Release a interface
SAFE_RELEASE(pMS) ;
// Release a interface
SAFE_RELEASE(pMC) ;
// Query for media seeking interfaces
IMediaSeeking * pMS ;
JIF(m_pGB->QueryInterface(IID_IMediaSeeking, (void **)&pMS)) ;
if (pMS != NULL)
{
// Rewind the graph to rewind the media file
LONGLONG pos;
LIF(pMS->GetPositions(&pos, NULL)) ;
// Query for media seeking interfaces
IMediaSeeking * pMS ;
JIF(m_pGB->QueryInterface(IID_IMediaSeeking, (void **)&pMS)) ;
if (pMS != NULL)
{
// Fastforward the graph to fastforward the media file
LONGLONG pos;
LIF(pMS->GetPositions(&pos, NULL)) ;
// Query for media seeking interfaces
IMediaSeeking * pMS ;
JIF(m_pGB->QueryInterface(IID_IMediaSeeking, (void **)&pMS)) ;
if (pMS != NULL)
{
// Go to the previous of the graph, usually the very first.
LONGLONG pos = 0;
LIF(pMS->SetPositions(&pos, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning)) ;
}
// Release a interface
SAFE_RELEASE(pMS) ;
return hr ;
}
HRESULT CMPlayer1App::OnNextClip()
{
HRESULT hr ;
if (m_pGB == NULL)
JIF(OnFileOpen()) ;
// Query for media seeking interfaces
IMediaSeeking * pMS ;
JIF(m_pGB->QueryInterface(IID_IMediaSeeking, (void **)&pMS)) ;
if (pMS != NULL)
{
// Go to the next of the graph, usually the very end.
LONGLONG pos;
LIF(pMS->GetPositions(NULL, &pos)) ;
LIF(pMS->SetPositions(&pos, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning)) ;
}
// Release a interface
SAFE_RELEASE(pMS) ;
HRESULT CMPlayer1App::OnSize()
{
if (m_pGB == NULL)
return E_ABORT ;
HRESULT hr ;
IVideoWindow * pVW;
JIF(m_pGB->QueryInterface(IID_IVideoWindow, (void **)&pVW));
if (pVW != NULL)
{
// Track the movement of the container window and resize as needed
RECT rcToolbar;
GetWindowRect(m_hwndToolBar, &rcToolbar);
int nToolbarHeight = rcToolbar.bottom - rcToolbar.top;
//------------------------------------------------------------------------------
// Name: CMPlayer1App::XXXFullScreen()
// 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.
//------------------------------------------------------------------------------
HRESULT CMPlayer1App::StartFullScreen()
{
if (m_pGB == NULL)
return E_ABORT ;
HRESULT hr ;
// Query for video interfaces
IVideoWindow * pVW ;
JIF(m_pGB->QueryInterface(IID_IVideoWindow, (void **)&pVW)) ;
if (!pVW)
return E_FAIL ;
// store the original window position
long lLeft, lTop, lWidth, lHeight ;
JIF(pVW->GetWindowPosition(&lLeft, &lTop, &lWidth, &lHeight)) ;
SetRect(&m_rectOrgVideo, lLeft, lTop, lLeft + lWidth, lTop + lHeight) ;
// save the original window style
JIF(pVW->get_WindowStyle(&m_lOrgStyle)) ;
JIF(pVW->get_WindowStyleEx(&m_lOrgStyleEx)) ;
// the window can't be a child while it is full screen
// or it can't be stretched beyond the parent window's borders
JIF(pVW->put_Owner(NULL)) ;
JIF(pVW->put_MessageDrain((OAHWND)m_hWnd)) ;
// modify the window's style
// ... remove these styles
JIF(pVW->put_WindowStyle(m_lOrgStyle & ~(WS_BORDER|WS_CAPTION|WS_THICKFRAME))) ;
// ... remove these extended styles
JIF(pVW->put_WindowStyleEx(m_lOrgStyleEx \
& ~(WS_EX_CLIENTEDGE|WS_EX_STATICEDGE|WS_EX_WINDOWEDGE|WS_EX_DLGMODALFRAME) \
| WS_EX_TOPMOST)) ;
// stretch the window to the full size of the screen
long lScrnWidth = GetSystemMetrics(SM_CXSCREEN) ;
long lScrnHeight = GetSystemMetrics(SM_CYSCREEN) ;
JIF(pVW->SetWindowPosition(0, 0, lScrnWidth, lScrnHeight)) ;
::ShowCursor(FALSE) ; // make sure to show mouse now
m_bFullScreenOn = true;
// Release a interface
SAFE_RELEASE(pVW) ;
return true ;
}
HRESULT CMPlayer1App::StopFullScreen()
{
if (m_pGB == NULL)
return E_ABORT ;
HRESULT hr ;
// Query for video interfaces
IVideoWindow * pVW ;
JIF(m_pGB->QueryInterface(IID_IVideoWindow, (void **)&pVW)) ;
if (!(pVW != NULL))
return E_FAIL ;
// Track the movement of the container window and resize as needed
RECT rcToolbar;
GetWindowRect(m_hwndToolBar, &rcToolbar);
int nToolbarHeight = rcToolbar.bottom - rcToolbar.top ;
// restore the window's position
RECT rect;
GetClientRect(m_hWnd, &rect);
JIF(pVW->SetWindowPosition(0, nToolbarHeight, rect.right, rect.bottom-nToolbarHeight)) ;
// make it a child window again
JIF(pVW->put_Owner(reinterpret_cast<OAHWND>(m_hWnd))) ;
// restore the window's styles
// ... restore the styles
JIF(pVW->put_WindowStyle(m_lOrgStyle)) ;
// ... restore the extended styles
JIF(pVW->put_WindowStyleEx(m_lOrgStyleEx)) ;
::ShowCursor(TRUE) ; // make sure to show mouse now
m_bFullScreenOn = false;
// 이 루프에서 그냥 리턴하면 Release()할 수 없으므로 조심한다!
while (SUCCEEDED(pME->GetEvent(&lEvent, &lParam1, &lParam2, lTimeOut)))
{
switch (lEvent)
{
case EC_USERABORT:
OnStopClip();
break;
//------------------------------------------------------------------------------
// Global data
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Name: WinMain()
// Desc: This method is the standard Windows program entry point.
//------------------------------------------------------------------------------
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
g_App.SetAppValues(hInstance, APPNAME, IDS_APP_TITLE) ;
// Main message loop:
MSG msg ;
while (GetMessage(&msg, NULL, 0, 0))
{
if (! TranslateAccelerator(msg.hwnd, hAccelTable, &msg) )
{
TranslateMessage(&msg) ;
DispatchMessage(&msg) ;
}
}
return (msg.wParam) ;
}
//------------------------------------------------------------------------------
// Name: WndProc()
// Desc: This method is our main window procedure. It parses the messages
// and farms out the work to other procedures.
// Note: It's a static function. We should use g_App to access members.
//------------------------------------------------------------------------------
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_GRAPHNOTIFY:
g_App.HandleGraphEvent(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) ;
g_App.OnSize() ;
return (DefWindowProc(hWnd, message, wParam, lParam)) ;
break ;
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.
//------------------------------------------------------------------------------
if (TTN_GETDISPINFO == TText->hdr.code)
{
switch (TText->hdr.idFrom)
{
case IDM_PLAYBACK_PLAY:
TText->lpszText = TEXT("Play") ;
break ;
case IDM_PLAYBACK_PAUSE:
TText->lpszText = TEXT("Pause") ;
break ;
case IDM_PLAYBACK_STOP:
TText->lpszText = TEXT("Stop") ;
break ;
case IDM_PLAYBACK_REWIND:
TText->lpszText = TEXT("Rewind") ;
break ;
case IDM_PLAYBACK_FASTFORWARD:
TText->lpszText = TEXT("FastForward") ;
break ;
case IDM_PLAYBACK_PREVIOUS:
TText->lpszText = TEXT("Previous") ;
break ;
case IDM_PLAYBACK_NEXT:
TText->lpszText = TEXT("Next") ;
break ;
// TODO: Place code here.
}
return (0) ;
}
else
return (DefWindowProc(hWnd, message, wParam, lParam)) ; // it wasn't a tooltip message
}
//------------------------------------------------------------------------------
// Name: CMPlayer1App::MenuProc()
// Desc: This method handles all of the menu messages for our application. It is
// passed these messages by the main message proc.
//------------------------------------------------------------------------------
// Parse the menu selections:
switch (LOWORD(wParam))
{
case IDM_EXIT:
DestroyWindow(m_hWnd) ;
break ;
case IDM_FILE_OPEN:
OnFileOpen() ;
break ;
case IDM_FILE_CLOSE:
OnFileClose() ;
break ;
case IDM_PLAYBACK_PLAY:
OnPlayClip() ;
break ;
case IDM_PLAYBACK_PAUSE:
OnPauseClip() ;
break ;
case IDM_PLAYBACK_STOP:
OnStopClip() ;
break ;
case IDM_PLAYBACK_REWIND:
OnRewindClip() ;
break ;
case IDM_PLAYBACK_FASTFORWARD:
OnFastForwardClip() ;
break ;
case IDM_PLAYBACK_PREVIOUS:
OnPreviousClip() ;
break ;
case IDM_PLAYBACK_NEXT:
OnNextClip() ;
break ;
// TODO: Place code here.
default:
break ;
}
return (0);
}
//------------------------------------------------------------------------------
// Name: CMPlayer1App::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 CMPlayer1App::KeyProc(WPARAM wParam, LPARAM lParam)
{
switch (wParam)
{
case VK_ESCAPE: // exit full screen
DestroyWindow(m_hWnd);
break ;
case VK_RETURN: // activate the currently selected button
break ;
case VK_LEFT: // select the left button
OnBalance(false);
break ;
case VK_RIGHT: // select the right button
OnBalance(true);
break ;
case VK_DOWN: // select the lower button
OnVolume(false);
break ;
case VK_UP: // select the upper button
OnVolume(true);
break ;
// TODO: Place code here.
case 'F':
ToggleFullScreen();
break ;