Show MainFrm.cpp syntax highlighted
/*
* Copyright (C) 2003-2006 Gabest
* http://www.gabest.org
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
// MainFrm.cpp : implementation of the CMainFrame class
//
#include "stdafx.h"
#include "mplayerc.h"
#include "MainFrm.h"
#include <math.h>
#include <afxpriv.h>
#include <atlconv.h>
#include <atlrx.h>
#include <atlsync.h>
#include "OpenFileDlg.h"
#include "OpenDlg.h"
#include "SaveDlg.h"
#include "GoToDlg.h"
#include "PnSPresetsDlg.h"
#include "MediaTypesDlg.h"
#include "SaveTextFileDialog.h"
#include "SaveThumbnailsDialog.h"
#include "FavoriteAddDlg.h"
#include "FavoriteOrganizeDlg.h"
#include "ConvertDlg.h"
#include "ShaderCombineDlg.h"
#include <mtype.h>
#include <Mpconfig.h>
#include <ks.h>
#include <ksmedia.h>
#include <dvdevcod.h>
#include <dsound.h>
#include <initguid.h>
#include <uuids.h>
#include "..\..\..\include\moreuuids.h"
#include <Qnetwork.h>
#include <qedit.h>
#include "..\..\DSUtil\DSUtil.h"
#include "FGManager.h"
#include "textpassthrufilter.h"
#include "..\..\filters\filters.h"
#include "..\..\filters\PinInfoWnd.h"
#include "DX7AllocatorPresenter.h"
#include "DX9AllocatorPresenter.h"
#include "..\..\subtitles\SSF.h"
#define DEFCLIENTW 292
#define DEFCLIENTH 200
static UINT s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
static UINT WM_NOTIFYICON = RegisterWindowMessage(TEXT("MYWM_NOTIFYICON"));
#include "..\..\filters\transform\vsfilter\IDirectVobSub.h"
class CSubClock : public CUnknown, public ISubClock
{
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv)
{
return
QI(ISubClock)
CUnknown::NonDelegatingQueryInterface(riid, ppv);
}
REFERENCE_TIME m_rt;
public:
CSubClock() : CUnknown(NAME("CSubClock"), NULL) {m_rt = 0;}
DECLARE_IUNKNOWN;
// ISubClock
STDMETHODIMP SetTime(REFERENCE_TIME rt) {m_rt = rt; return S_OK;}
STDMETHODIMP_(REFERENCE_TIME) GetTime() {return(m_rt);}
};
//
#define SaveMediaState \
OAFilterState __fs = GetMediaState(); \
\
REFERENCE_TIME __rt = 0; \
if(m_iMediaLoadState == MLS_LOADED) __rt = GetPos(); \
\
if(__fs != State_Stopped) \
SendMessage(WM_COMMAND, ID_PLAY_STOP); \
#define RestoreMediaState \
if(m_iMediaLoadState == MLS_LOADED) \
{ \
SeekTo(__rt); \
\
if(__fs == State_Stopped) \
SendMessage(WM_COMMAND, ID_PLAY_STOP); \
else if(__fs == State_Paused) \
SendMessage(WM_COMMAND, ID_PLAY_PAUSE); \
else if(__fs == State_Running) \
SendMessage(WM_COMMAND, ID_PLAY_PLAY); \
} \
/*
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
*/
/////////////////////////////////////////////////////////////////////////////
// CMainFrame
IMPLEMENT_DYNAMIC(CMainFrame, CFrameWnd)
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
ON_WM_CREATE()
ON_WM_DESTROY()
ON_WM_CLOSE()
ON_REGISTERED_MESSAGE(s_uTaskbarRestart, OnTaskBarRestart)
ON_REGISTERED_MESSAGE(WM_NOTIFYICON, OnNotifyIcon)
ON_WM_SETFOCUS()
ON_WM_GETMINMAXINFO()
ON_WM_MOVE()
ON_WM_MOVING()
ON_WM_SIZE()
ON_WM_SIZING()
ON_MESSAGE_VOID(WM_DISPLAYCHANGE, OnDisplayChange)
ON_WM_SYSCOMMAND()
ON_WM_ACTIVATEAPP()
ON_MESSAGE(WM_APPCOMMAND, OnAppCommand)
ON_WM_TIMER()
ON_MESSAGE(WM_GRAPHNOTIFY, OnGraphNotify)
ON_MESSAGE(WM_REARRANGERENDERLESS, OnRepaintRenderLess)
ON_MESSAGE(WM_RESUMEFROMSTATE, OnResumeFromState)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_LBUTTONDBLCLK()
ON_WM_MBUTTONDOWN()
ON_WM_MBUTTONUP()
ON_WM_MBUTTONDBLCLK()
ON_WM_RBUTTONDOWN()
ON_WM_RBUTTONUP()
ON_WM_RBUTTONDBLCLK()
ON_MESSAGE(WM_XBUTTONDOWN, OnXButtonDown)
ON_MESSAGE(WM_XBUTTONUP, OnXButtonUp)
ON_MESSAGE(WM_XBUTTONDBLCLK, OnXButtonDblClk)
ON_WM_MOUSEWHEEL()
ON_WM_MOUSEMOVE()
ON_WM_NCHITTEST()
ON_WM_HSCROLL()
ON_WM_INITMENU()
ON_WM_INITMENUPOPUP()
ON_COMMAND(ID_MENU_PLAYER_SHORT, OnMenuPlayerShort)
ON_COMMAND(ID_MENU_PLAYER_LONG, OnMenuPlayerLong)
ON_COMMAND(ID_MENU_FILTERS, OnMenuFilters)
ON_UPDATE_COMMAND_UI(IDC_PLAYERSTATUS, OnUpdatePlayerStatus)
ON_COMMAND(ID_FILE_POST_OPENMEDIA, OnFilePostOpenmedia)
ON_UPDATE_COMMAND_UI(ID_FILE_POST_OPENMEDIA, OnUpdateFilePostOpenmedia)
ON_COMMAND(ID_FILE_POST_CLOSEMEDIA, OnFilePostClosemedia)
ON_UPDATE_COMMAND_UI(ID_FILE_POST_CLOSEMEDIA, OnUpdateFilePostClosemedia)
ON_COMMAND(ID_BOSS, OnBossKey)
ON_COMMAND_RANGE(ID_STREAM_AUDIO_NEXT, ID_STREAM_AUDIO_PREV, OnStreamAudio)
ON_COMMAND_RANGE(ID_STREAM_SUB_NEXT, ID_STREAM_SUB_PREV, OnStreamSub)
ON_COMMAND(ID_STREAM_SUB_ONOFF, OnStreamSubOnOff)
ON_COMMAND_RANGE(ID_OGM_AUDIO_NEXT, ID_OGM_AUDIO_PREV, OnOgmAudio)
ON_COMMAND_RANGE(ID_OGM_SUB_NEXT, ID_OGM_SUB_PREV, OnOgmSub)
ON_COMMAND_RANGE(ID_DVD_ANGLE_NEXT, ID_DVD_ANGLE_PREV, OnDvdAngle)
ON_COMMAND_RANGE(ID_DVD_AUDIO_NEXT, ID_DVD_AUDIO_PREV, OnDvdAudio)
ON_COMMAND_RANGE(ID_DVD_SUB_NEXT, ID_DVD_SUB_PREV, OnDvdSub)
ON_COMMAND(ID_DVD_SUB_ONOFF, OnDvdSubOnOff)
ON_COMMAND(ID_FILE_OPENQUICK, OnFileOpenQuick)
ON_UPDATE_COMMAND_UI(ID_FILE_OPENMEDIA, OnUpdateFileOpen)
ON_COMMAND(ID_FILE_OPENMEDIA, OnFileOpenmedia)
ON_UPDATE_COMMAND_UI(ID_FILE_OPENMEDIA, OnUpdateFileOpen)
ON_WM_COPYDATA()
ON_COMMAND(ID_FILE_OPENDVD, OnFileOpendvd)
ON_UPDATE_COMMAND_UI(ID_FILE_OPENDVD, OnUpdateFileOpen)
ON_COMMAND(ID_FILE_OPENDEVICE, OnFileOpendevice)
ON_UPDATE_COMMAND_UI(ID_FILE_OPENDEVICE, OnUpdateFileOpen)
ON_COMMAND_RANGE(ID_FILE_OPEN_CD_START, ID_FILE_OPEN_CD_END, OnFileOpenCD)
ON_UPDATE_COMMAND_UI_RANGE(ID_FILE_OPEN_CD_START, ID_FILE_OPEN_CD_END, OnUpdateFileOpen)
ON_WM_DROPFILES()
ON_COMMAND(ID_FILE_SAVE_COPY, OnFileSaveAs)
ON_UPDATE_COMMAND_UI(ID_FILE_SAVE_COPY, OnUpdateFileSaveAs)
ON_COMMAND(ID_FILE_SAVE_IMAGE, OnFileSaveImage)
ON_UPDATE_COMMAND_UI(ID_FILE_SAVE_IMAGE, OnUpdateFileSaveImage)
ON_COMMAND(ID_FILE_SAVE_IMAGE_AUTO, OnFileSaveImageAuto)
ON_UPDATE_COMMAND_UI(ID_FILE_SAVE_IMAGE_AUTO, OnUpdateFileSaveImage)
ON_COMMAND(ID_FILE_SAVE_THUMBNAILS, OnFileSaveThumbnails)
ON_UPDATE_COMMAND_UI(ID_FILE_SAVE_THUMBNAILS, OnUpdateFileSaveThumbnails)
ON_COMMAND(ID_FILE_CONVERT, OnFileConvert)
ON_UPDATE_COMMAND_UI(ID_FILE_CONVERT, OnUpdateFileConvert)
ON_COMMAND(ID_FILE_LOAD_SUBTITLE, OnFileLoadsubtitle)
ON_UPDATE_COMMAND_UI(ID_FILE_LOAD_SUBTITLE, OnUpdateFileLoadsubtitle)
ON_COMMAND(ID_FILE_SAVE_SUBTITLE, OnFileSavesubtitle)
ON_UPDATE_COMMAND_UI(ID_FILE_SAVE_SUBTITLE, OnUpdateFileSavesubtitle)
ON_COMMAND(ID_FILE_ISDB_SEARCH, OnFileISDBSearch)
ON_UPDATE_COMMAND_UI(ID_FILE_ISDB_SEARCH, OnUpdateFileISDBSearch)
ON_COMMAND(ID_FILE_ISDB_UPLOAD, OnFileISDBUpload)
ON_UPDATE_COMMAND_UI(ID_FILE_ISDB_UPLOAD, OnUpdateFileISDBUpload)
ON_COMMAND(ID_FILE_ISDB_DOWNLOAD, OnFileISDBDownload)
ON_UPDATE_COMMAND_UI(ID_FILE_ISDB_DOWNLOAD, OnUpdateFileISDBDownload)
ON_COMMAND(ID_FILE_PROPERTIES, OnFileProperties)
ON_UPDATE_COMMAND_UI(ID_FILE_PROPERTIES, OnUpdateFileProperties)
ON_COMMAND(ID_FILE_CLOSEPLAYLIST, OnFileClosePlaylist)
ON_COMMAND(ID_FILE_CLOSEMEDIA, OnFileCloseMedia)
ON_UPDATE_COMMAND_UI(ID_FILE_CLOSEMEDIA, OnUpdateFileClose)
ON_COMMAND(ID_VIEW_CAPTIONMENU, OnViewCaptionmenu)
ON_UPDATE_COMMAND_UI(ID_VIEW_CAPTIONMENU, OnUpdateViewCaptionmenu)
ON_COMMAND_RANGE(ID_VIEW_SEEKER, ID_VIEW_STATUS, OnViewControlBar)
ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_SEEKER, ID_VIEW_STATUS, OnUpdateViewControlBar)
ON_COMMAND(ID_VIEW_SUBRESYNC, OnViewSubresync)
ON_UPDATE_COMMAND_UI(ID_VIEW_SUBRESYNC, OnUpdateViewSubresync)
ON_COMMAND(ID_VIEW_PLAYLIST, OnViewPlaylist)
ON_UPDATE_COMMAND_UI(ID_VIEW_PLAYLIST, OnUpdateViewPlaylist)
ON_COMMAND(ID_VIEW_CAPTURE, OnViewCapture)
ON_UPDATE_COMMAND_UI(ID_VIEW_CAPTURE, OnUpdateViewCapture)
ON_COMMAND(ID_VIEW_SHADEREDITOR, OnViewShaderEditor)
ON_UPDATE_COMMAND_UI(ID_VIEW_SHADEREDITOR, OnUpdateViewShaderEditor)
ON_COMMAND(ID_VIEW_PRESETS_MINIMAL, OnViewMinimal)
ON_UPDATE_COMMAND_UI(ID_VIEW_PRESETS_MINIMAL, OnUpdateViewMinimal)
ON_COMMAND(ID_VIEW_PRESETS_COMPACT, OnViewCompact)
ON_UPDATE_COMMAND_UI(ID_VIEW_PRESETS_COMPACT, OnUpdateViewCompact)
ON_COMMAND(ID_VIEW_PRESETS_NORMAL, OnViewNormal)
ON_UPDATE_COMMAND_UI(ID_VIEW_PRESETS_NORMAL, OnUpdateViewNormal)
ON_COMMAND(ID_VIEW_FULLSCREEN, OnViewFullscreen)
ON_COMMAND(ID_VIEW_FULLSCREEN_SECONDARY, OnViewFullscreenSecondary)
ON_UPDATE_COMMAND_UI(ID_VIEW_FULLSCREEN, OnUpdateViewFullscreen)
ON_COMMAND_RANGE(ID_VIEW_ZOOM_50, ID_VIEW_ZOOM_200, OnViewZoom)
ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_ZOOM_50, ID_VIEW_ZOOM_200, OnUpdateViewZoom)
ON_COMMAND(ID_VIEW_ZOOM_AUTOFIT, OnViewZoomAutoFit)
ON_UPDATE_COMMAND_UI(ID_VIEW_ZOOM_AUTOFIT, OnUpdateViewZoom)
ON_COMMAND_RANGE(ID_VIEW_VF_HALF, ID_VIEW_VF_FROMOUTSIDE, OnViewDefaultVideoFrame)
ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_VF_HALF, ID_VIEW_VF_FROMOUTSIDE, OnUpdateViewDefaultVideoFrame)
ON_COMMAND(ID_VIEW_VF_KEEPASPECTRATIO, OnViewKeepaspectratio)
ON_UPDATE_COMMAND_UI(ID_VIEW_VF_KEEPASPECTRATIO, OnUpdateViewKeepaspectratio)
ON_COMMAND(ID_VIEW_VF_COMPMONDESKARDIFF, OnViewCompMonDeskARDiff)
ON_UPDATE_COMMAND_UI(ID_VIEW_VF_COMPMONDESKARDIFF, OnUpdateViewCompMonDeskARDiff)
ON_COMMAND_RANGE(ID_VIEW_RESET, ID_PANSCAN_CENTER, OnViewPanNScan)
ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_RESET, ID_PANSCAN_CENTER, OnUpdateViewPanNScan)
ON_COMMAND_RANGE(ID_PANNSCAN_PRESETS_START, ID_PANNSCAN_PRESETS_END, OnViewPanNScanPresets)
ON_UPDATE_COMMAND_UI_RANGE(ID_PANNSCAN_PRESETS_START, ID_PANNSCAN_PRESETS_END, OnUpdateViewPanNScanPresets)
ON_COMMAND_RANGE(ID_PANSCAN_ROTATEXP, ID_PANSCAN_ROTATEZM, OnViewRotate)
ON_UPDATE_COMMAND_UI_RANGE(ID_PANSCAN_ROTATEXP, ID_PANSCAN_ROTATEZM, OnUpdateViewRotate)
ON_COMMAND_RANGE(ID_ASPECTRATIO_START, ID_ASPECTRATIO_END, OnViewAspectRatio)
ON_UPDATE_COMMAND_UI_RANGE(ID_ASPECTRATIO_START, ID_ASPECTRATIO_END, OnUpdateViewAspectRatio)
ON_COMMAND(ID_ASPECTRATIO_NEXT, OnViewAspectRatioNext)
ON_COMMAND_RANGE(ID_ONTOP_NEVER, ID_ONTOP_WHILEPLAYING, OnViewOntop)
ON_UPDATE_COMMAND_UI_RANGE(ID_ONTOP_NEVER, ID_ONTOP_WHILEPLAYING, OnUpdateViewOntop)
ON_COMMAND(ID_VIEW_OPTIONS, OnViewOptions)
ON_COMMAND(ID_PLAY_PLAY, OnPlayPlay)
ON_COMMAND(ID_PLAY_PAUSE, OnPlayPause)
ON_COMMAND(ID_PLAY_PLAYPAUSE, OnPlayPlaypause)
ON_COMMAND(ID_PLAY_STOP, OnPlayStop)
ON_UPDATE_COMMAND_UI(ID_PLAY_PLAY, OnUpdatePlayPauseStop)
ON_UPDATE_COMMAND_UI(ID_PLAY_PAUSE, OnUpdatePlayPauseStop)
ON_UPDATE_COMMAND_UI(ID_PLAY_PLAYPAUSE, OnUpdatePlayPauseStop)
ON_UPDATE_COMMAND_UI(ID_PLAY_STOP, OnUpdatePlayPauseStop)
ON_COMMAND_RANGE(ID_PLAY_FRAMESTEP, ID_PLAY_FRAMESTEPCANCEL, OnPlayFramestep)
ON_UPDATE_COMMAND_UI_RANGE(ID_PLAY_FRAMESTEP, ID_PLAY_FRAMESTEPCANCEL, OnUpdatePlayFramestep)
ON_COMMAND_RANGE(ID_PLAY_SEEKBACKWARDSMALL, ID_PLAY_SEEKFORWARDLARGE, OnPlaySeek)
ON_COMMAND_RANGE(ID_PLAY_SEEKKEYBACKWARD, ID_PLAY_SEEKKEYFORWARD, OnPlaySeekKey)
ON_UPDATE_COMMAND_UI_RANGE(ID_PLAY_SEEKBACKWARDSMALL, ID_PLAY_SEEKFORWARDLARGE, OnUpdatePlaySeek)
ON_UPDATE_COMMAND_UI_RANGE(ID_PLAY_SEEKKEYBACKWARD, ID_PLAY_SEEKKEYFORWARD, OnUpdatePlaySeek)
ON_COMMAND(ID_PLAY_GOTO, OnPlayGoto)
ON_UPDATE_COMMAND_UI(ID_PLAY_GOTO, OnUpdateGoto)
ON_COMMAND_RANGE(ID_PLAY_DECRATE, ID_PLAY_INCRATE, OnPlayChangeRate)
ON_UPDATE_COMMAND_UI_RANGE(ID_PLAY_DECRATE, ID_PLAY_INCRATE, OnUpdatePlayChangeRate)
ON_COMMAND(ID_PLAY_RESETRATE, OnPlayResetRate)
ON_UPDATE_COMMAND_UI(ID_PLAY_RESETRATE, OnUpdatePlayResetRate)
ON_COMMAND_RANGE(ID_PLAY_INCAUDDELAY, ID_PLAY_DECAUDDELAY, OnPlayChangeAudDelay)
ON_UPDATE_COMMAND_UI_RANGE(ID_PLAY_INCAUDDELAY, ID_PLAY_DECAUDDELAY, OnUpdatePlayChangeAudDelay)
ON_COMMAND_RANGE(ID_FILTERS_SUBITEM_START, ID_FILTERS_SUBITEM_END, OnPlayFilters)
ON_UPDATE_COMMAND_UI_RANGE(ID_FILTERS_SUBITEM_START, ID_FILTERS_SUBITEM_END, OnUpdatePlayFilters)
ON_COMMAND_RANGE(ID_SHADERS_START, ID_SHADERS_END, OnPlayShaders)
ON_UPDATE_COMMAND_UI_RANGE(ID_SHADERS_START, ID_SHADERS_END, OnUpdatePlayShaders)
ON_COMMAND_RANGE(ID_AUDIO_SUBITEM_START, ID_AUDIO_SUBITEM_END, OnPlayAudio)
ON_UPDATE_COMMAND_UI_RANGE(ID_AUDIO_SUBITEM_START, ID_AUDIO_SUBITEM_END, OnUpdatePlayAudio)
ON_COMMAND_RANGE(ID_SUBTITLES_SUBITEM_START, ID_SUBTITLES_SUBITEM_END, OnPlaySubtitles)
ON_UPDATE_COMMAND_UI_RANGE(ID_SUBTITLES_SUBITEM_START, ID_SUBTITLES_SUBITEM_END, OnUpdatePlaySubtitles)
ON_COMMAND_RANGE(ID_FILTERSTREAMS_SUBITEM_START, ID_FILTERSTREAMS_SUBITEM_END, OnPlayLanguage)
ON_UPDATE_COMMAND_UI_RANGE(ID_FILTERSTREAMS_SUBITEM_START, ID_FILTERSTREAMS_SUBITEM_END, OnUpdatePlayLanguage)
ON_COMMAND_RANGE(ID_VOLUME_UP, ID_VOLUME_MUTE, OnPlayVolume)
ON_COMMAND_RANGE(ID_VOLUME_BOOST_INC, ID_VOLUME_BOOST_MAX, OnPlayVolumeBoost)
ON_UPDATE_COMMAND_UI_RANGE(ID_VOLUME_BOOST_INC, ID_VOLUME_BOOST_MAX, OnUpdatePlayVolumeBoost)
ON_COMMAND_RANGE(ID_AFTERPLAYBACK_CLOSE, ID_AFTERPLAYBACK_DONOTHING, OnAfterplayback)
ON_UPDATE_COMMAND_UI_RANGE(ID_AFTERPLAYBACK_CLOSE, ID_AFTERPLAYBACK_DONOTHING, OnUpdateAfterplayback)
ON_COMMAND_RANGE(ID_NAVIGATE_SKIPBACK, ID_NAVIGATE_SKIPFORWARD, OnNavigateSkip)
ON_UPDATE_COMMAND_UI_RANGE(ID_NAVIGATE_SKIPBACK, ID_NAVIGATE_SKIPFORWARD, OnUpdateNavigateSkip)
ON_COMMAND_RANGE(ID_NAVIGATE_SKIPBACKPLITEM, ID_NAVIGATE_SKIPFORWARDPLITEM, OnNavigateSkipPlaylistItem)
ON_UPDATE_COMMAND_UI_RANGE(ID_NAVIGATE_SKIPBACKPLITEM, ID_NAVIGATE_SKIPFORWARDPLITEM, OnUpdateNavigateSkipPlaylistItem)
ON_COMMAND_RANGE(ID_NAVIGATE_TITLEMENU, ID_NAVIGATE_CHAPTERMENU, OnNavigateMenu)
ON_UPDATE_COMMAND_UI_RANGE(ID_NAVIGATE_TITLEMENU, ID_NAVIGATE_CHAPTERMENU, OnUpdateNavigateMenu)
ON_COMMAND_RANGE(ID_NAVIGATE_AUDIO_SUBITEM_START, ID_NAVIGATE_AUDIO_SUBITEM_END, OnNavigateAudio)
ON_COMMAND_RANGE(ID_NAVIGATE_SUBP_SUBITEM_START, ID_NAVIGATE_SUBP_SUBITEM_END, OnNavigateSubpic)
ON_COMMAND_RANGE(ID_NAVIGATE_ANGLE_SUBITEM_START, ID_NAVIGATE_ANGLE_SUBITEM_END, OnNavigateAngle)
ON_COMMAND_RANGE(ID_NAVIGATE_CHAP_SUBITEM_START, ID_NAVIGATE_CHAP_SUBITEM_END, OnNavigateChapters)
ON_COMMAND_RANGE(ID_NAVIGATE_MENU_LEFT, ID_NAVIGATE_MENU_LEAVE, OnNavigateMenuItem)
ON_UPDATE_COMMAND_UI_RANGE(ID_NAVIGATE_MENU_LEFT, ID_NAVIGATE_MENU_LEAVE, OnUpdateNavigateMenuItem)
ON_COMMAND(ID_FAVORITES_ADD, OnFavoritesAdd)
ON_UPDATE_COMMAND_UI(ID_FAVORITES_ADD, OnUpdateFavoritesAdd)
ON_COMMAND(ID_FAVORITES_ORGANIZE, OnFavoritesOrganize)
ON_UPDATE_COMMAND_UI(ID_FAVORITES_ORGANIZE, OnUpdateFavoritesOrganize)
ON_COMMAND_RANGE(ID_FAVORITES_FILE_START, ID_FAVORITES_FILE_END, OnFavoritesFile)
ON_UPDATE_COMMAND_UI_RANGE(ID_FAVORITES_FILE_START, ID_FAVORITES_FILE_END, OnUpdateFavoritesFile)
ON_COMMAND_RANGE(ID_FAVORITES_DVD_START, ID_FAVORITES_DVD_END, OnFavoritesDVD)
ON_UPDATE_COMMAND_UI_RANGE(ID_FAVORITES_DVD_START, ID_FAVORITES_DVD_END, OnUpdateFavoritesDVD)
ON_COMMAND_RANGE(ID_FAVORITES_DEVICE_START, ID_FAVORITES_DEVICE_END, OnFavoritesDevice)
ON_UPDATE_COMMAND_UI_RANGE(ID_FAVORITES_DEVICE_START, ID_FAVORITES_DEVICE_END, OnUpdateFavoritesDevice)
ON_COMMAND(ID_HELP_HOMEPAGE, OnHelpHomepage)
ON_COMMAND(ID_HELP_DOCUMENTATION, OnHelpDocumentation)
ON_COMMAND(ID_HELP_DONATE, OnHelpDonate)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMainFrame construction/destruction
#pragma warning(disable : 4355)
CMainFrame::CMainFrame() :
m_dwRegister(0),
m_iMediaLoadState(MLS_CLOSED),
m_iPlaybackMode(PM_NONE),
m_iSpeedLevel(0),
m_rtDurationOverride(-1),
m_fFullScreen(false),
m_fHideCursor(false),
m_lastMouseMove(-1, -1),
m_pLastBar(NULL),
m_nLoops(0),
m_iSubtitleSel(-1),
m_ZoomX(1), m_ZoomY(1), m_PosX(0.5), m_PosY(0.5),
m_AngleX(0), m_AngleY(0), m_AngleZ(0),
m_fCustomGraph(false),
m_fRealMediaGraph(false), m_fShockwaveGraph(false), m_fQuicktimeGraph(false),
m_fFrameSteppingActive(false),
m_fEndOfStream(false),
m_fCapturing(false),
m_fLiveWM(false),
m_fOpeningAborted(false),
m_fBuffering(false),
m_fileDropTarget(this),
m_fTrayIcon(false)
{
}
CMainFrame::~CMainFrame()
{
// m_owner.DestroyWindow();
}
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if(__super::OnCreate(lpCreateStruct) == -1)
return -1;
m_popup.LoadMenu(IDR_POPUP);
m_popupmain.LoadMenu(IDR_POPUPMAIN);
GetMenu()->ModifyMenu(ID_FAVORITES, MF_BYCOMMAND|MF_STRING, IDR_MAINFRAME, ResStr(IDS_FAVORITES_POPUP));
// create a view to occupy the client area of the frame
if(!m_wndView.Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,
CRect(0, 0, 0, 0), this, AFX_IDW_PANE_FIRST, NULL))
{
TRACE0("Failed to create view window\n");
return -1;
}
// static bars
if(!m_wndStatusBar.Create(this)
|| !m_wndStatsBar.Create(this)
|| !m_wndInfoBar.Create(this)
|| !m_wndToolBar.Create(this)
|| !m_wndSeekBar.Create(this))
{
TRACE0("Failed to create all control bars\n");
return -1; // fail to create
}
m_bars.AddTail(&m_wndSeekBar);
m_bars.AddTail(&m_wndToolBar);
m_bars.AddTail(&m_wndInfoBar);
m_bars.AddTail(&m_wndStatsBar);
m_bars.AddTail(&m_wndStatusBar);
m_wndSeekBar.Enable(false);
// dockable bars
EnableDocking(CBRS_ALIGN_ANY);
m_dockingbars.RemoveAll();
m_wndSubresyncBar.Create(this, &m_csSubLock);
m_wndSubresyncBar.SetBarStyle(m_wndSubresyncBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
m_wndSubresyncBar.EnableDocking(CBRS_ALIGN_ANY);
m_wndSubresyncBar.SetHeight(200);
LoadControlBar(&m_wndSubresyncBar, AFX_IDW_DOCKBAR_TOP);
m_wndPlaylistBar.Create(this);
m_wndPlaylistBar.SetBarStyle(m_wndPlaylistBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
m_wndPlaylistBar.EnableDocking(CBRS_ALIGN_ANY);
m_wndPlaylistBar.SetHeight(100);
LoadControlBar(&m_wndPlaylistBar, AFX_IDW_DOCKBAR_BOTTOM);
m_wndPlaylistBar.LoadPlaylist();
m_wndCaptureBar.Create(this);
m_wndCaptureBar.SetBarStyle(m_wndCaptureBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
m_wndCaptureBar.EnableDocking(CBRS_ALIGN_LEFT|CBRS_ALIGN_RIGHT);
LoadControlBar(&m_wndCaptureBar, AFX_IDW_DOCKBAR_LEFT);
m_wndShaderEditorBar.Create(this);
m_wndShaderEditorBar.SetBarStyle(m_wndShaderEditorBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
m_wndShaderEditorBar.EnableDocking(CBRS_ALIGN_ANY);
LoadControlBar(&m_wndShaderEditorBar, AFX_IDW_DOCKBAR_TOP);
m_fileDropTarget.Register(this);
GetDesktopWindow()->GetWindowRect(&m_rcDesktop);
AppSettings& s = AfxGetAppSettings();
ShowControls(s.nCS);
SetAlwaysOnTop(s.iOnTop);
ShowTrayIcon(s.fTrayIcon);
SetFocus();
m_pGraphThread = (CGraphThread*)AfxBeginThread(RUNTIME_CLASS(CGraphThread));
if(m_pGraphThread)
m_pGraphThread->SetMainFrame(this);
if(s.fEnableWebServer)
StartWebServer(s.nWebServerPort);
return 0;
}
void CMainFrame::OnDestroy()
{
ShowTrayIcon(false);
m_fileDropTarget.Revoke();
if(m_pGraphThread)
{
CAMEvent e;
m_pGraphThread->PostThreadMessage(CGraphThread::TM_EXIT, 0, (LPARAM)&e);
if(!e.Wait(5000))
{
TRACE(_T("ERROR: Must call TerminateThread() on CMainFrame::m_pGraphThread->m_hThread\n"));
TerminateThread(m_pGraphThread->m_hThread, -1);
}
}
__super::OnDestroy();
}
void CMainFrame::OnClose()
{
m_wndPlaylistBar.SavePlaylist();
SaveControlBars();
ShowWindow(SW_HIDE);
CloseMedia();
__super::OnClose();
}
DROPEFFECT CMainFrame::OnDragEnter(COleDataObject* pDataObject, DWORD dwKeyState, CPoint point)
{
return DROPEFFECT_NONE;
}
DROPEFFECT CMainFrame::OnDragOver(COleDataObject* pDataObject, DWORD dwKeyState, CPoint point)
{
UINT CF_URL = RegisterClipboardFormat(_T("UniformResourceLocator"));
return pDataObject->IsDataAvailable(CF_URL) ? DROPEFFECT_COPY : DROPEFFECT_NONE;
}
BOOL CMainFrame::OnDrop(COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point)
{
UINT CF_URL = RegisterClipboardFormat(_T("UniformResourceLocator"));
BOOL bResult = FALSE;
if(pDataObject->IsDataAvailable(CF_URL))
{
FORMATETC fmt = {CF_URL, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
if(HGLOBAL hGlobal = pDataObject->GetGlobalData(CF_URL, &fmt))
{
LPCSTR pText = (LPCSTR)GlobalLock(hGlobal);
if(AfxIsValidString(pText))
{
CStringA url(pText);
SetForegroundWindow();
CAtlList<CString> sl;
sl.AddTail(CString(url));
if(m_wndPlaylistBar.IsWindowVisible())
{
m_wndPlaylistBar.Append(sl, true);
}
else
{
m_wndPlaylistBar.Open(sl, true);
OpenCurPlaylistItem();
}
GlobalUnlock(hGlobal);
bResult = TRUE;
}
}
}
return bResult;
}
DROPEFFECT CMainFrame::OnDropEx(COleDataObject* pDataObject, DROPEFFECT dropDefault, DROPEFFECT dropList, CPoint point)
{
return (DROPEFFECT)-1;
}
void CMainFrame::OnDragLeave()
{
}
DROPEFFECT CMainFrame::OnDragScroll(DWORD dwKeyState, CPoint point)
{
return DROPEFFECT_NONE;
}
void CMainFrame::LoadControlBar(CControlBar* pBar, UINT defDockBarID)
{
if(!pBar) return;
CString str;
pBar->GetWindowText(str);
if(str.IsEmpty()) return;
CString section = _T("ToolBars\\") + str;
CWinApp* pApp = AfxGetApp();
UINT nID = pApp->GetProfileInt(section, _T("DockState"), defDockBarID);
if(nID != AFX_IDW_DOCKBAR_FLOAT)
{
DockControlBar(pBar, nID);
}
pBar->ShowWindow(
pApp->GetProfileInt(section, _T("Visible"), FALSE)
&& pBar != &m_wndSubresyncBar
&& pBar != &m_wndCaptureBar
&& pBar != &m_wndShaderEditorBar
? SW_SHOW
: SW_HIDE);
if(CSizingControlBar* pSCB = dynamic_cast<CSizingControlBar*>(pBar))
{
pSCB->LoadState(section + _T("\\State"));
m_dockingbars.AddTail(pSCB);
}
}
void CMainFrame::RestoreFloatingControlBars()
{
CWinApp* pApp = AfxGetApp();
CRect r;
GetWindowRect(r);
POSITION pos = m_dockingbars.GetHeadPosition();
while(pos)
{
CSizingControlBar* pBar = m_dockingbars.GetNext(pos);
CString str;
pBar->GetWindowText(str);
if(str.IsEmpty()) return;
CString section = _T("ToolBars\\") + str;
if(pApp->GetProfileInt(section, _T("DockState"), ~AFX_IDW_DOCKBAR_FLOAT) == AFX_IDW_DOCKBAR_FLOAT)
{
CPoint p;
p.x = pApp->GetProfileInt(section, _T("DockPosX"), r.right);
p.y = pApp->GetProfileInt(section, _T("DockPosY"), r.top);
if(p.x < m_rcDesktop.left) p.x = m_rcDesktop.left;
if(p.y < m_rcDesktop.top) p.y = m_rcDesktop.top;
if(p.x >= m_rcDesktop.right) p.x = m_rcDesktop.right-1;
if(p.y >= m_rcDesktop.bottom) p.y = m_rcDesktop.bottom-1;
FloatControlBar(pBar, p);
}
}
}
void CMainFrame::SaveControlBars()
{
CWinApp* pApp = AfxGetApp();
POSITION pos = m_dockingbars.GetHeadPosition();
while(pos)
{
CSizingControlBar* pBar = m_dockingbars.GetNext(pos);
CString str;
pBar->GetWindowText(str);
if(str.IsEmpty()) return;
CString section = _T("ToolBars\\") + str;
pApp->WriteProfileInt(section, _T("Visible"), pBar->IsWindowVisible());
if(CSizingControlBar* pSCB = dynamic_cast<CSizingControlBar*>(pBar))
{
pSCB->SaveState(section + _T("\\State"));
}
UINT nID = pBar->GetParent()->GetDlgCtrlID();
if(nID == AFX_IDW_DOCKBAR_FLOAT)
{
CRect r;
pBar->GetParent()->GetParent()->GetWindowRect(r);
pApp->WriteProfileInt(section, _T("DockPosX"), r.left);
pApp->WriteProfileInt(section, _T("DockPosY"), r.top);
}
pApp->WriteProfileInt(section, _T("DockState"), nID);
}
}
LRESULT CMainFrame::OnTaskBarRestart(WPARAM, LPARAM)
{
m_fTrayIcon = false;
ShowTrayIcon(AfxGetAppSettings().fTrayIcon);
return 0;
}
LRESULT CMainFrame::OnNotifyIcon(WPARAM wParam, LPARAM lParam)
{
if((UINT)wParam != IDR_MAINFRAME)
return -1;
switch((UINT)lParam)
{
case WM_LBUTTONDOWN:
ShowWindow(SW_SHOW);
MoveVideoWindow();
SetForegroundWindow();
break;
case WM_LBUTTONDBLCLK:
PostMessage(WM_COMMAND, ID_FILE_OPENMEDIA);
break;
case WM_RBUTTONDOWN:
{
POINT p;
GetCursorPos(&p);
SetForegroundWindow();
m_popupmain.GetSubMenu(0)->TrackPopupMenu(TPM_RIGHTBUTTON|TPM_NOANIMATION, p.x, p.y, this);
PostMessage(WM_NULL);
break;
}
case WM_MOUSEMOVE:
{
CString str;
GetWindowText(str);
SetTrayTip(str);
break;
}
default:
break;
}
return 0;
}
void CMainFrame::ShowTrayIcon(bool fShow)
{
BOOL bWasVisible = ShowWindow(SW_HIDE);
if(fShow)
{
if(!m_fTrayIcon)
{
NOTIFYICONDATA tnid;
tnid.cbSize = sizeof(NOTIFYICONDATA);
tnid.hWnd = m_hWnd;
tnid.uID = IDR_MAINFRAME;
// tnid.hIcon = (HICON)LoadIcon(AfxGetResourceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME));
tnid.hIcon = (HICON)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
tnid.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP;
tnid.uCallbackMessage = WM_NOTIFYICON;
lstrcpyn(tnid.szTip, TEXT("Media Player Classic"), sizeof(tnid.szTip));
Shell_NotifyIcon(NIM_ADD, &tnid);
m_fTrayIcon = true;
}
}
else
{
if(m_fTrayIcon)
{
NOTIFYICONDATA tnid;
tnid.cbSize = sizeof(NOTIFYICONDATA);
tnid.hWnd = m_hWnd;
tnid.uID = IDR_MAINFRAME;
Shell_NotifyIcon(NIM_DELETE, &tnid);
m_fTrayIcon = false;
}
}
if(bWasVisible)
ShowWindow(SW_SHOW);
}
void CMainFrame::SetTrayTip(CString str)
{
NOTIFYICONDATA tnid;
tnid.cbSize = sizeof(NOTIFYICONDATA);
tnid.hWnd = m_hWnd;
tnid.uID = IDR_MAINFRAME;
tnid.uFlags = NIF_TIP;
lstrcpyn(tnid.szTip, str, sizeof(tnid.szTip));
Shell_NotifyIcon(NIM_MODIFY, &tnid);
}
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if(!__super::PreCreateWindow(cs))
return FALSE;
cs.dwExStyle &= ~WS_EX_CLIENTEDGE;
cs.lpszClass = MPC_WND_CLASS_NAME; //AfxRegisterWndClass(0);
return TRUE;
}
BOOL CMainFrame::PreTranslateMessage(MSG* pMsg)
{
if(pMsg->message == WM_KEYDOWN)
{
/* if(m_fShockwaveGraph
&& (pMsg->wParam == VK_LEFT || pMsg->wParam == VK_RIGHT
|| pMsg->wParam == VK_UP || pMsg->wParam == VK_DOWN))
return FALSE;
*/
if(pMsg->wParam == VK_ESCAPE && m_iMediaLoadState == MLS_LOADED && m_fFullScreen)
{
OnViewFullscreen();
PostMessage(WM_COMMAND, ID_PLAY_PAUSE);
return TRUE;
}
else if(pMsg->wParam == VK_ESCAPE && (IsCaptionMenuHidden()))
{
PostMessage(WM_COMMAND, ID_VIEW_CAPTIONMENU);
return TRUE;
}
else if(pMsg->wParam == VK_LEFT && pAMTuner)
{
PostMessage(WM_COMMAND, ID_NAVIGATE_SKIPBACK);
return TRUE;
}
else if(pMsg->wParam == VK_RIGHT && pAMTuner)
{
PostMessage(WM_COMMAND, ID_NAVIGATE_SKIPFORWARD);
return TRUE;
}
}
return __super::PreTranslateMessage(pMsg);
}
void CMainFrame::RecalcLayout(BOOL bNotify)
{
__super::RecalcLayout(bNotify);
CRect r;
GetWindowRect(&r);
MINMAXINFO mmi;
memset(&mmi, 0, sizeof(mmi));
SendMessage(WM_GETMINMAXINFO, 0, (LPARAM)&mmi);
r |= CRect(r.TopLeft(), CSize(r.Width(), mmi.ptMinTrackSize.y));
MoveWindow(&r);
}
/////////////////////////////////////////////////////////////////////////////
// CMainFrame diagnostics
#ifdef _DEBUG
void CMainFrame::AssertValid() const
{
__super::AssertValid();
}
void CMainFrame::Dump(CDumpContext& dc) const
{
__super::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CMainFrame message handlers
void CMainFrame::OnSetFocus(CWnd* pOldWnd)
{
SetAlwaysOnTop(AfxGetAppSettings().iOnTop);
// forward focus to the view window
if(IsWindow(m_wndView.m_hWnd))
m_wndView.SetFocus();
}
BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
{
// let the view have first crack at the command
if(m_wndView.OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
return TRUE;
POSITION pos = m_bars.GetHeadPosition();
while(pos)
{
if(m_bars.GetNext(pos)->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
return TRUE;
}
pos = m_dockingbars.GetHeadPosition();
while(pos)
{
if(m_dockingbars.GetNext(pos)->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
return TRUE;
}
// otherwise, do default handling
return __super::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}
void CMainFrame::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
{
DWORD style = GetStyle();
MENUBARINFO mbi;
memset(&mbi, 0, sizeof(mbi));
mbi.cbSize = sizeof(mbi);
::GetMenuBarInfo(m_hWnd, OBJID_MENU, 0, &mbi);
lpMMI->ptMinTrackSize.x = 0;
if(!IsCaptionMenuHidden())
{
lpMMI->ptMinTrackSize.x = 10;
CRect r;
for(int i = 0; ::GetMenuItemRect(m_hWnd, mbi.hMenu, i, &r); i++)
lpMMI->ptMinTrackSize.x += r.Width();
lpMMI->ptMinTrackSize.x = max(DEFCLIENTW, lpMMI->ptMinTrackSize.x);
}
if(style&WS_THICKFRAME) lpMMI->ptMinTrackSize.x += GetSystemMetrics((style&WS_CAPTION)?SM_CXSIZEFRAME:SM_CXFIXEDFRAME)*2;
memset(&mbi, 0, sizeof(mbi));
mbi.cbSize = sizeof(mbi);
::GetMenuBarInfo(m_hWnd, OBJID_MENU, 0, &mbi);
lpMMI->ptMinTrackSize.y = 0;
if(style&WS_CAPTION) lpMMI->ptMinTrackSize.y += GetSystemMetrics(SM_CYCAPTION);
if(style&WS_THICKFRAME) lpMMI->ptMinTrackSize.y += GetSystemMetrics((style&WS_CAPTION)?SM_CYSIZEFRAME:SM_CYFIXEDFRAME)*2;
lpMMI->ptMinTrackSize.y += (mbi.rcBar.bottom - mbi.rcBar.top);
if(!AfxGetAppSettings().fHideCaptionMenu) lpMMI->ptMinTrackSize.y += 3;
POSITION pos = m_bars.GetHeadPosition();
while(pos)
{
CControlBar* pCB = m_bars.GetNext(pos);
if(!IsWindow(pCB->m_hWnd) || !pCB->IsVisible()) continue;
lpMMI->ptMinTrackSize.y += pCB->CalcFixedLayout(TRUE, TRUE).cy;
}
pos = m_dockingbars.GetHeadPosition();
while(pos)
{
CSizingControlBar* pCB = m_dockingbars.GetNext(pos);
if(IsWindow(pCB->m_hWnd) && pCB->IsWindowVisible() && !pCB->IsFloating())
lpMMI->ptMinTrackSize.y += pCB->CalcFixedLayout(TRUE, TRUE).cy-2;
}
__super::OnGetMinMaxInfo(lpMMI);
}
void CMainFrame::OnMove(int x, int y)
{
__super::OnMove(x, y);
MoveVideoWindow();
WINDOWPLACEMENT wp;
GetWindowPlacement(&wp);
if(!m_fFullScreen && wp.flags != WPF_RESTORETOMAXIMIZED && wp.showCmd != SW_SHOWMINIMIZED)
GetWindowRect(AfxGetAppSettings().rcLastWindowPos);
}
void CMainFrame::OnMoving(UINT fwSide, LPRECT pRect)
{
__super::OnMoving(fwSide, pRect);
if(AfxGetAppSettings().fSnapToDesktopEdges)
{
const CPoint threshold(3, 3);
CRect r0 = m_rcDesktop;
CRect r1 = r0 + threshold;
CRect r2 = r0 - threshold;
RECT& wr = *pRect;
CSize ws = CRect(wr).Size();
if(wr.left < r1.left && wr.left > r2.left)
wr.right = (wr.left = r0.left) + ws.cx;
if(wr.top < r1.top && wr.top > r2.top)
wr.bottom = (wr.top = r0.top) + ws.cy;
if(wr.right < r1.right && wr.right > r2.right)
wr.left = (wr.right = r0.right) - ws.cx;
if(wr.bottom < r1.bottom && wr.bottom > r2.bottom)
wr.top = (wr.bottom = r0.bottom) - ws.cy;
}
}
void CMainFrame::OnSize(UINT nType, int cx, int cy)
{
__super::OnSize(nType, cx, cy);
if(nType == SIZE_RESTORED && m_fTrayIcon)
{
ShowWindow(SW_SHOW);
}
if(!m_fFullScreen)
{
AppSettings& s = AfxGetAppSettings();
if(nType != SIZE_MAXIMIZED && nType != SIZE_MINIMIZED)
GetWindowRect(s.rcLastWindowPos);
s.lastWindowType = nType;
}
}
void CMainFrame::OnSizing(UINT fwSide, LPRECT pRect)
{
__super::OnSizing(fwSide, pRect);
AppSettings& s = AfxGetAppSettings();
bool fCtrl = !!(GetAsyncKeyState(VK_CONTROL)&0x80000000);
if(m_iMediaLoadState != MLS_LOADED || m_fFullScreen
|| s.iDefaultVideoSize == DVS_STRETCH
|| (fCtrl ^ s.fFreeWindowResizing))
return;
CSize wsize(pRect->right - pRect->left, pRect->bottom - pRect->top);
CSize vsize = GetVideoSize();
CSize fsize(0, 0);
if(!vsize.cx || !vsize.cy)
return;
// TODO
{
DWORD style = GetStyle();
MENUBARINFO mbi;
memset(&mbi, 0, sizeof(mbi));
mbi.cbSize = sizeof(mbi);
::GetMenuBarInfo(m_hWnd, OBJID_MENU, 0, &mbi);
fsize.cx += GetSystemMetrics((style&WS_CAPTION)?SM_CXSIZEFRAME:SM_CXFIXEDFRAME)*2;
if(style&WS_CAPTION) fsize.cy += GetSystemMetrics(SM_CYCAPTION);
if(style&WS_THICKFRAME) fsize.cy += GetSystemMetrics((style&WS_CAPTION)?SM_CYSIZEFRAME:SM_CYFIXEDFRAME)*2;
fsize.cy += mbi.rcBar.bottom - mbi.rcBar.top;
if(!AfxGetAppSettings().fHideCaptionMenu) fsize.cy += 3;
POSITION pos = m_bars.GetHeadPosition();
while(pos)
{
CControlBar* pCB = m_bars.GetNext(pos);
if(IsWindow(pCB->m_hWnd) && pCB->IsVisible())
fsize.cy += pCB->CalcFixedLayout(TRUE, TRUE).cy;
}
pos = m_dockingbars.GetHeadPosition();
while(pos)
{
CSizingControlBar* pCB = m_dockingbars.GetNext(pos);
if(IsWindow(pCB->m_hWnd) && pCB->IsWindowVisible())
{
if(pCB->IsHorzDocked()) fsize.cy += pCB->CalcFixedLayout(TRUE, TRUE).cy-2;
else if(pCB->IsVertDocked()) fsize.cx += pCB->CalcFixedLayout(TRUE, FALSE).cx;
}
}
}
wsize -= fsize;
bool fWider = wsize.cy < wsize.cx;
wsize.SetSize(
wsize.cy * vsize.cx / vsize.cy,
wsize.cx * vsize.cy / vsize.cx);
wsize += fsize;
if(fwSide == WMSZ_TOP || fwSide == WMSZ_BOTTOM || !fWider && (fwSide == WMSZ_TOPRIGHT || fwSide == WMSZ_BOTTOMRIGHT))
{
pRect->right = pRect->left + wsize.cx;
}
else if(fwSide == WMSZ_LEFT || fwSide == WMSZ_RIGHT || fWider && (fwSide == WMSZ_BOTTOMLEFT || fwSide == WMSZ_BOTTOMRIGHT))
{
pRect->bottom = pRect->top + wsize.cy;
}
else if(!fWider && (fwSide == WMSZ_TOPLEFT || fwSide == WMSZ_BOTTOMLEFT))
{
pRect->left = pRect->right - wsize.cx;
}
else if(fWider && (fwSide == WMSZ_TOPLEFT || fwSide == WMSZ_TOPRIGHT))
{
pRect->top = pRect->bottom - wsize.cy;
}
}
void CMainFrame::OnDisplayChange() // untested, not sure if it's working...
{
TRACE(_T("*** CMainFrame::OnDisplayChange()\n"));
/*
if(m_iMediaLoadState == MLS_LOADED && m_pCAP)
m_pCAP->OnDisplayChange();
*/
GetDesktopWindow()->GetWindowRect(&m_rcDesktop);
}
#include <psapi.h>
void CMainFrame::OnSysCommand(UINT nID, LPARAM lParam)
{
if((nID & 0xFFF0) == SC_SCREENSAVE)
{
TRACE(_T("SC_SCREENSAVE, nID = %d, lParam = %d\n"), nID, lParam);
}
else if((nID & 0xFFF0) == SC_MINIMIZE && m_fTrayIcon)
{
ShowWindow(SW_HIDE);
return;
}
__super::OnSysCommand(nID, lParam);
}
void CMainFrame::OnActivateApp(BOOL bActive, DWORD dwThreadID)
{
__super::OnActivateApp(bActive, dwThreadID);
MONITORINFO mi;
mi.cbSize = sizeof(MONITORINFO);
GetMonitorInfo(MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST), &mi);
if(!bActive && (mi.dwFlags&MONITORINFOF_PRIMARY) && m_fFullScreen && m_iMediaLoadState == MLS_LOADED)
{
bool fExitFullscreen = true;
if(CWnd* pWnd = GetForegroundWindow())
{
HMONITOR hMonitor1 = MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST);
HMONITOR hMonitor2 = MonitorFromWindow(pWnd->m_hWnd, MONITOR_DEFAULTTONEAREST);
if(hMonitor1 && hMonitor2 && hMonitor1 != hMonitor2) fExitFullscreen = false;
CString title;
pWnd->GetWindowText(title);
CString module;
if(GetVersion()&0x80000000)
{
module.ReleaseBufferSetLength(GetWindowModuleFileName(pWnd->m_hWnd, module.GetBuffer(MAX_PATH), MAX_PATH));
}
else
{
DWORD pid;
GetWindowThreadProcessId(pWnd->m_hWnd, &pid);
if(HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid))
{
HMODULE hMod;
DWORD cbNeeded;
if(EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded))
{
module.ReleaseBufferSetLength(GetModuleFileNameEx(hProcess, hMod, module.GetBuffer(MAX_PATH), MAX_PATH));
}
CloseHandle(hProcess);
}
}
CPath p(module);
p.StripPath();
module = (LPCTSTR)p;
module.MakeLower();
CString str;
str.Format(_T("Focus lost to: %s - %s"), module, title);
SendStatusMessage(str, 5000);
}
if(fExitFullscreen) OnViewFullscreen();
}
}
LRESULT CMainFrame::OnAppCommand(WPARAM wParam, LPARAM lParam)
{
UINT cmd = GET_APPCOMMAND_LPARAM(lParam);
UINT uDevice = GET_DEVICE_LPARAM(lParam);
UINT dwKeys = GET_KEYSTATE_LPARAM(lParam);
if(uDevice != FAPPCOMMAND_OEM)
{
AppSettings& s = AfxGetAppSettings();
BOOL fRet = FALSE;
POSITION pos = s.wmcmds.GetHeadPosition();
while(pos)
{
wmcmd& wc = s.wmcmds.GetNext(pos);
if(wc.appcmd == cmd && TRUE == SendMessage(WM_COMMAND, wc.cmd))
fRet = TRUE;
}
if(fRet) return TRUE;
}
return Default();
}
void CMainFrame::OnTimer(UINT nIDEvent)
{
if(nIDEvent == TIMER_STREAMPOSPOLLER && m_iMediaLoadState == MLS_LOADED)
{
REFERENCE_TIME rtNow = 0, rtDur = 0;
if(m_iPlaybackMode == PM_FILE)
{
pMS->GetCurrentPosition(&rtNow);
pMS->GetDuration(&rtDur);
if(m_rtDurationOverride >= 0) rtDur = m_rtDurationOverride;
m_wndSeekBar.Enable(rtDur > 0);
m_wndSeekBar.SetRange(0, rtDur);
m_wndSeekBar.SetPos(rtNow);
}
else if(m_iPlaybackMode == PM_CAPTURE)
{
if(m_fCapturing && m_wndCaptureBar.m_capdlg.m_pMux)
{
CComQIPtr<IMediaSeeking> pMuxMS = m_wndCaptureBar.m_capdlg.m_pMux;
if(!pMuxMS || FAILED(pMuxMS->GetCurrentPosition(&rtNow))) rtNow = 0;
}
if(m_rtDurationOverride >= 0) rtDur = m_rtDurationOverride;
m_wndSeekBar.Enable(false);
m_wndSeekBar.SetRange(0, rtDur);
m_wndSeekBar.SetPos(rtNow);
/*
if(m_fCapturing)
{
if(rtNow > 10000i64*1000*60*60*3)
{
m_wndCaptureBar.m_capdlg.OnRecord();
}
}
*/
}
if(m_pCAP && m_iPlaybackMode != PM_FILE) m_pCAP->SetTime(/*rtNow*/m_wndSeekBar.GetPos());
}
else if(nIDEvent == TIMER_STREAMPOSPOLLER2 && m_iMediaLoadState == MLS_LOADED)
{
__int64 start, stop, pos;
m_wndSeekBar.GetRange(start, stop);
pos = m_wndSeekBar.GetPosReal();
GUID tf;
pMS->GetTimeFormat(&tf);
if(m_iPlaybackMode == PM_CAPTURE && !m_fCapturing)
{
CString str = _T("Live");
long lChannel = 0, lVivSub = 0, lAudSub = 0;
if(pAMTuner
&& m_wndCaptureBar.m_capdlg.IsTunerActive()
&& SUCCEEDED(pAMTuner->get_Channel(&lChannel, &lVivSub, &lAudSub)))
{
CString ch;
ch.Format(_T(" (ch%d)"), lChannel);
str += ch;
}
m_wndStatusBar.SetStatusTimer(str);
}
else
{
m_wndStatusBar.SetStatusTimer(pos, stop, !!m_wndSubresyncBar.IsWindowVisible(), &tf);
}
m_wndSubresyncBar.SetTime(pos);
if(m_pCAP && GetMediaState() == State_Paused) m_pCAP->Paint(true);
}
else if(nIDEvent == TIMER_FULLSCREENCONTROLBARHIDER)
{
CPoint p;
GetCursorPos(&p);
CRect r;
GetWindowRect(r);
bool fCursorOutside = !r.PtInRect(p);
CWnd* pWnd = WindowFromPoint(p);
if(pWnd && (m_wndView == *pWnd || m_wndView.IsChild(pWnd) || fCursorOutside))
{
if(AfxGetAppSettings().nShowBarsWhenFullScreenTimeOut >= 0)
ShowControls(CS_NONE, false);
}
}
else if(nIDEvent == TIMER_FULLSCREENMOUSEHIDER)
{
CPoint p;
GetCursorPos(&p);
CRect r;
GetWindowRect(r);
bool fCursorOutside = !r.PtInRect(p);
CWnd* pWnd = WindowFromPoint(p);
if(pWnd && (m_wndView == *pWnd || m_wndView.IsChild(pWnd) || fCursorOutside))
{
m_fHideCursor = true;
SetCursor(NULL);
}
}
else if(nIDEvent == TIMER_STATS)
{
if(pQP)
{
CString rate;
if(m_iSpeedLevel >= -11 && m_iSpeedLevel <= 3 && m_iSpeedLevel != -4)
{
CString speeds[] = {_T("1/8"),_T("1/4"),_T("1/2"),_T("1"),_T("2"),_T("4"),_T("8")};
rate = speeds[(m_iSpeedLevel >= -3 ? m_iSpeedLevel : (-m_iSpeedLevel - 8)) + 3];
if(m_iSpeedLevel < -4) rate = _T("-") + rate;
if(!rate.IsEmpty()) rate = _T("(") + rate + _T("X)");
}
CString info;
int val;
pQP->get_AvgFrameRate(&val);
info.Format(_T("%d.%02d %s"), val/100, val%100, rate);
m_wndStatsBar.SetLine(_T("Frame-rate"), info);
int avg, dev;
pQP->get_AvgSyncOffset(&avg);
pQP->get_DevSyncOffset(&dev);
info.Format(_T("avg: %d ms, dev: %d ms"), avg, dev);
m_wndStatsBar.SetLine(_T("Sync Offset"), info);
int drawn, dropped;
pQP->get_FramesDrawn(&drawn);
pQP->get_FramesDroppedInRenderer(&dropped);
info.Format(_T("drawn: %d, dropped: %d"), drawn, dropped);
m_wndStatsBar.SetLine(_T("Frames"), info);
pQP->get_Jitter(&val);
info.Format(_T("%d ms"), val);
m_wndStatsBar.SetLine(_T("Jitter"), info);
}
if(pBI)
{
CAtlList<CString> sl;
for(int i = 0, j = pBI->GetCount(); i < j; i++)
{
int samples, size;
if(S_OK == pBI->GetStatus(i, samples, size))
{
CString str;
str.Format(_T("[%d]: %03d/%d KB"), i, samples, size / 1024);
sl.AddTail(str);
}
}
if(!sl.IsEmpty())
{
CString str;
str.Format(_T("%s (p%d)"), Implode(sl, ' '), pBI->GetPriority());
m_wndStatsBar.SetLine(_T("Buffers"), str);
}
}
CInterfaceList<IBitRateInfo> pBRIs;
BeginEnumFilters(pGB, pEF, pBF)
{
BeginEnumPins(pBF, pEP, pPin)
{
if(CComQIPtr<IBitRateInfo> pBRI = pPin)
{
pBRIs.AddTail(pBRI);
}
}
EndEnumPins
if(!pBRIs.IsEmpty())
{
CAtlList<CString> sl;
POSITION pos = pBRIs.GetHeadPosition();
for(int i = 0; pos; i++)
{
IBitRateInfo* pBRI = pBRIs.GetNext(pos);
DWORD cur = pBRI->GetCurrentBitRate() / 1000;
DWORD avg = pBRI->GetAverageBitRate() / 1000;
if(avg == 0) continue;
CString str;
if(cur != avg) str.Format(_T("[%d]: %d/%d Kb/s"), i, avg, cur);
else str.Format(_T("[%d]: %d Kb/s"), i, avg);
sl.AddTail(str);
}
if(!sl.IsEmpty())
{
m_wndStatsBar.SetLine(_T("Bitrate"), Implode(sl, ' ') + _T(" (avg/cur)"));
}
break;
}
}
EndEnumFilters
if(m_iPlaybackMode == PM_FILE)
{
SetupChapters();
}
if(m_iPlaybackMode == PM_DVD) // we also use this timer to update the info panel for dvd playback
{
ULONG ulAvailable, ulCurrent;
// Location
CString Location('-');
DVD_PLAYBACK_LOCATION2 loc;
ULONG ulNumOfVolumes, ulVolume;
DVD_DISC_SIDE Side;
ULONG ulNumOfTitles;
ULONG ulNumOfChapters;
if(SUCCEEDED(pDVDI->GetCurrentLocation(&loc))
&& SUCCEEDED(pDVDI->GetNumberOfChapters(loc.TitleNum, &ulNumOfChapters))
&& SUCCEEDED(pDVDI->GetDVDVolumeInfo(&ulNumOfVolumes, &ulVolume, &Side, &ulNumOfTitles)))
{
Location.Format(_T("Volume: %02d/%02d, Title: %02d/%02d, Chapter: %02d/%02d"),
ulVolume, ulNumOfVolumes,
loc.TitleNum, ulNumOfTitles,
loc.ChapterNum, ulNumOfChapters);
}
m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_LOCATION), Location);
// Video
CString Video('-');
DVD_VideoAttributes VATR;
if(SUCCEEDED(pDVDI->GetCurrentAngle(&ulAvailable, &ulCurrent))
&& SUCCEEDED(pDVDI->GetCurrentVideoAttributes(&VATR)))
{
Video.Format(_T("Angle: %02d/%02d, %dx%d %dHz %d:%d"),
ulAvailable, ulCurrent,
VATR.ulSourceResolutionX, VATR.ulSourceResolutionY, VATR.ulFrameRate,
VATR.ulAspectX, VATR.ulAspectY);
}
m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_VIDEO), Video);
// Audio
CString Audio('-');
DVD_AudioAttributes AATR;
if(SUCCEEDED(pDVDI->GetCurrentAudio(&ulAvailable, &ulCurrent))
&& SUCCEEDED(pDVDI->GetAudioAttributes(ulCurrent, &AATR)))
{
CString lang;
int len = GetLocaleInfo(AATR.Language, LOCALE_SENGLANGUAGE, lang.GetBuffer(64), 64);
lang.ReleaseBufferSetLength(max(len-1, 0));
switch(AATR.LanguageExtension)
{
case DVD_AUD_EXT_NotSpecified:
default: break;
case DVD_AUD_EXT_Captions: lang += _T(" (Captions)"); break;
case DVD_AUD_EXT_VisuallyImpaired: lang += _T(" (Visually Impaired)"); break;
case DVD_AUD_EXT_DirectorComments1: lang += _T(" (Director Comments 1)"); break;
case DVD_AUD_EXT_DirectorComments2: lang += _T(" (Director Comments 2)"); break;
}
CString format;
switch(AATR.AudioFormat)
{
case DVD_AudioFormat_AC3: format = _T("AC3"); break;
case DVD_AudioFormat_MPEG1:
case DVD_AudioFormat_MPEG1_DRC: format = _T("MPEG1"); break;
case DVD_AudioFormat_MPEG2:
case DVD_AudioFormat_MPEG2_DRC: format = _T("MPEG2"); break;
case DVD_AudioFormat_LPCM: format = _T("LPCM"); break;
case DVD_AudioFormat_DTS: format = _T("DTS"); break;
case DVD_AudioFormat_SDDS: format = _T("SDDS"); break;
case DVD_AudioFormat_Other:
default: format = _T("Unknown format"); break;
}
Audio.Format(_T("%s, %s %dHz %dbits %d channel(s)"),
lang,
format,
AATR.dwFrequency,
AATR.bQuantization,
AATR.bNumberOfChannels);
m_wndStatusBar.SetStatusBitmap(
AATR.bNumberOfChannels == 1 ? IDB_MONO
: AATR.bNumberOfChannels >= 2 ? IDB_STEREO
: IDB_NOAUDIO);
}
m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_AUDIO), Audio);
// Subtitles
CString Subtitles('-');
BOOL bIsDisabled;
DVD_SubpictureAttributes SATR;
if(SUCCEEDED(pDVDI->GetCurrentSubpicture(&ulAvailable, &ulCurrent, &bIsDisabled))
&& SUCCEEDED(pDVDI->GetSubpictureAttributes(ulCurrent, &SATR)))
{
CString lang;
int len = GetLocaleInfo(SATR.Language, LOCALE_SENGLANGUAGE, lang.GetBuffer(64), 64);
lang.ReleaseBufferSetLength(max(len-1, 0));
switch(SATR.LanguageExtension)
{
case DVD_SP_EXT_NotSpecified:
default: break;
case DVD_SP_EXT_Caption_Normal: lang += _T(""); break;
case DVD_SP_EXT_Caption_Big: lang += _T(" (Big)"); break;
case DVD_SP_EXT_Caption_Children: lang += _T(" (Children)"); break;
case DVD_SP_EXT_CC_Normal: lang += _T(" (CC)"); break;
case DVD_SP_EXT_CC_Big: lang += _T(" (CC Big)"); break;
case DVD_SP_EXT_CC_Children: lang += _T(" (CC Children)"); break;
case DVD_SP_EXT_Forced: lang += _T(" (Forced)"); break;
case DVD_SP_EXT_DirectorComments_Normal: lang += _T(" (Director Comments)"); break;
case DVD_SP_EXT_DirectorComments_Big: lang += _T(" (Director Comments, Big)"); break;
case DVD_SP_EXT_DirectorComments_Children: lang += _T(" (Director Comments, Children)"); break;
}
if(bIsDisabled) lang = _T("-");
Subtitles.Format(_T("%s"),
lang);
}
m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_SUBTITLES), Subtitles);
}
if(GetMediaState() == State_Running)
{
UINT fSaverActive = 0;
if(SystemParametersInfo(SPI_GETSCREENSAVEACTIVE, 0, (PVOID)&fSaverActive, 0))
{
SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, 0, 0, SPIF_SENDWININICHANGE); // this might not be needed at all...
SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, fSaverActive, 0, SPIF_SENDWININICHANGE);
}
fSaverActive = 0;
if(SystemParametersInfo(SPI_GETPOWEROFFACTIVE, 0, (PVOID)&fSaverActive, 0))
{
SystemParametersInfo(SPI_SETPOWEROFFACTIVE, 0, 0, SPIF_SENDWININICHANGE); // this might not be needed at all...
SystemParametersInfo(SPI_SETPOWEROFFACTIVE, fSaverActive, 0, SPIF_SENDWININICHANGE);
}
}
}
else if(nIDEvent == TIMER_STATUSERASER)
{
KillTimer(TIMER_STATUSERASER);
m_playingmsg.Empty();
}
__super::OnTimer(nIDEvent);
}
static bool SetShutdownPrivilege()
{
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
// Get a token for this process.
if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
return(false);
// Get the LUID for the shutdown privilege.
LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
tkp.PrivilegeCount = 1; // one privilege to set
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
// Get the shutdown privilege for this process.
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
if(GetLastError() != ERROR_SUCCESS)
return false;
return true;
}
bool CMainFrame::DoAfterPlaybackEvent()
{
AppSettings& s = AfxGetAppSettings();
bool fExit = false;
if(s.nCLSwitches&CLSW_CLOSE)
{
fExit = true;
}
if(s.nCLSwitches&CLSW_STANDBY)
{
SetShutdownPrivilege();
SetSystemPowerState(TRUE, TRUE);
fExit = true; // TODO: unless the app closes, it will call standby or hibernate once again forever, how to avoid that?
}
else if(s.nCLSwitches&CLSW_HIBERNATE)
{
SetShutdownPrivilege();
SetSystemPowerState(FALSE, TRUE);
fExit = true; // TODO: unless the app closes, it will call standby or hibernate once again forever, how to avoid that?
}
else if(s.nCLSwitches&CLSW_SHUTDOWN)
{
SetShutdownPrivilege();
ExitWindowsEx(EWX_SHUTDOWN|EWX_POWEROFF|EWX_FORCEIFHUNG, 0);
fExit = true;
}
else if(s.nCLSwitches&CLSW_LOGOFF)
{
SetShutdownPrivilege();
ExitWindowsEx(EWX_LOGOFF|EWX_FORCEIFHUNG, 0);
fExit = true;
}
if(!fExit) return false;
SendMessage(WM_COMMAND, ID_FILE_EXIT);
return true;
}
//
// our WM_GRAPHNOTIFY handler
//
#include <comdef.h>
LRESULT CMainFrame::OnGraphNotify(WPARAM wParam, LPARAM lParam)
{
HRESULT hr = S_OK;
LONG evCode, evParam1, evParam2;
while(pME && SUCCEEDED(pME->GetEvent(&evCode, (LONG_PTR*)&evParam1, (LONG_PTR*)&evParam2, 0)))
{
CString str;
if(m_fCustomGraph)
{
if(EC_BG_ERROR == evCode)
{
str = CString((char*)evParam1);
}
}
hr = pME->FreeEventParams(evCode, evParam1, evParam2);
if(EC_COMPLETE == evCode)
{
AppSettings& s = AfxGetAppSettings();
if(m_wndPlaylistBar.GetCount() <= 1)
{
m_nLoops++;
if(DoAfterPlaybackEvent()) return hr;
if(s.fLoopForever || m_nLoops < s.nLoops)
{
if(GetMediaState() == State_Stopped)
{
SendMessage(WM_COMMAND, ID_PLAY_PLAY);
}
else
{
LONGLONG pos = 0;
pMS->SetPositions(&pos, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning);
if(GetMediaState() == State_Paused)
{
SendMessage(WM_COMMAND, ID_PLAY_PLAY);
}
}
}
else
{
if(s.fRewind) SendMessage(WM_COMMAND, ID_PLAY_STOP);
else m_fEndOfStream = true;
SendMessage(WM_COMMAND, ID_PLAY_PAUSE);
if(m_fFullScreen && s.fExitFullScreenAtTheEnd)
OnViewFullscreen();
}
}
else if(m_wndPlaylistBar.GetCount() > 1)
{
if(m_wndPlaylistBar.IsAtEnd())
{
if(DoAfterPlaybackEvent()) return hr;
m_nLoops++;
}
if(s.fLoopForever || m_nLoops < s.nLoops)
{
int nLoops = m_nLoops;
PostMessage(WM_COMMAND, ID_NAVIGATE_SKIPFORWARD);
m_nLoops = nLoops;
}
else
{
if(m_fFullScreen && s.fExitFullScreenAtTheEnd)
OnViewFullscreen();
if(s.fRewind)
{
AfxGetAppSettings().nCLSwitches |= CLSW_OPEN; // HACK
PostMessage(WM_COMMAND, ID_NAVIGATE_SKIPFORWARD);
}
else
{
m_fEndOfStream = true;
PostMessage(WM_COMMAND, ID_PLAY_PAUSE);
}
}
}
}
else if(EC_ERRORABORT == evCode)
{
TRACE(_T("EC_ERRORABORT, hr = %08x\n"), (HRESULT)evParam1);
// SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
// m_closingmsg = _com_error((HRESULT)evParam1).ErrorMessage();
}
else if(EC_REPAINT == evCode)
{
TRACE(_T("EC_REPAINT\n"));
}
else if(EC_BUFFERING_DATA == evCode)
{
TRACE(_T("EC_BUFFERING_DATA, %d, %d\n"), (HRESULT)evParam1, evParam2);
m_fBuffering = ((HRESULT)evParam1 != S_OK);
}
else if(EC_STEP_COMPLETE == evCode)
{
if(m_fFrameSteppingActive)
{
m_fFrameSteppingActive = false;
pBA->put_Volume(m_VolumeBeforeFrameStepping);
}
}
else if(EC_DEVICE_LOST == evCode)
{
CComQIPtr<IBaseFilter> pBF;
if(m_iPlaybackMode == PM_CAPTURE
&& (!pVidCap && pVidCap == (pBF = (IUnknown*)evParam1)
|| !pAudCap && pAudCap == (pBF = (IUnknown*)evParam1))
&& evParam2 == 0)
{
SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
}
}
else if(EC_DVD_TITLE_CHANGE == evCode)
{
if(m_iPlaybackMode == PM_FILE)
{
SetupChapters();
}
else if(m_iPlaybackMode == PM_DVD)
{
m_iDVDTitle = (DWORD)evParam1;
if(m_iDVDDomain == DVD_DOMAIN_Title)
{
CString Domain;
Domain.Format(_T("Title %d"), m_iDVDTitle);
m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_DOMAIN), Domain);
}
}
}
else if(EC_DVD_DOMAIN_CHANGE == evCode)
{
m_iDVDDomain = (DVD_DOMAIN)evParam1;
CString Domain('-');
switch(m_iDVDDomain)
{
case DVD_DOMAIN_FirstPlay: Domain = _T("First Play"); break;
case DVD_DOMAIN_VideoManagerMenu: Domain = _T("Video Manager Menu"); break;
case DVD_DOMAIN_VideoTitleSetMenu: Domain = _T("Video Title Set Menu"); break;
case DVD_DOMAIN_Title: Domain.Format(_T("Title %d"), m_iDVDTitle); break;
case DVD_DOMAIN_Stop: Domain = _T("Stop"); break;
default: Domain = _T("-"); break;
}
m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_DOMAIN), Domain);
MoveVideoWindow(); // AR might have changed
}
else if(EC_DVD_CURRENT_HMSF_TIME == evCode)
{
double fps = evParam2 == DVD_TC_FLAG_25fps ? 25.0
: evParam2 == DVD_TC_FLAG_30fps ? 30.0
: evParam2 == DVD_TC_FLAG_DropFrame ? 29.97
: 25.0;
REFERENCE_TIME rtDur = 0;
DVD_HMSF_TIMECODE tcDur;
ULONG ulFlags;
if(SUCCEEDED(pDVDI->GetTotalTitleTime(&tcDur, &ulFlags)))
rtDur = HMSF2RT(tcDur, fps);
m_wndSeekBar.Enable(rtDur > 0);
m_wndSeekBar.SetRange(0, rtDur);
REFERENCE_TIME rtNow = HMSF2RT(*((DVD_HMSF_TIMECODE*)&evParam1), fps);
m_wndSeekBar.SetPos(rtNow);
if(m_pSubClock) m_pSubClock->SetTime(rtNow);
}
else if(EC_DVD_ERROR == evCode)
{
TRACE(_T("EC_DVD_ERROR %d %d\n"), evParam1, evParam2);
CString err;
switch(evParam1)
{
case DVD_ERROR_Unexpected: default: err = _T("DVD: Unexpected error"); break;
case DVD_ERROR_CopyProtectFail: err = _T("DVD: Copy-Protect Fail"); break;
case DVD_ERROR_InvalidDVD1_0Disc: err = _T("DVD: Invalid DVD 1.x Disc"); break;
case DVD_ERROR_InvalidDiscRegion: err = _T("DVD: Invalid Disc Region"); break;
case DVD_ERROR_LowParentalLevel: err = _T("DVD: Low Parental Level"); break;
case DVD_ERROR_MacrovisionFail: err = _T("DVD: Macrovision Fail"); break;
case DVD_ERROR_IncompatibleSystemAndDecoderRegions: err = _T("DVD: Incompatible System And Decoder Regions"); break;
case DVD_ERROR_IncompatibleDiscAndDecoderRegions: err = _T("DVD: Incompatible Disc And Decoder Regions"); break;
}
SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
m_closingmsg = err;
}
else if(EC_DVD_WARNING == evCode)
{
TRACE(_T("EC_DVD_WARNING %d %d\n"), evParam1, evParam2);
}
else if(EC_VIDEO_SIZE_CHANGED == evCode)
{
TRACE(_T("EC_VIDEO_SIZE_CHANGED %dx%d\n"), CSize(evParam1));
WINDOWPLACEMENT wp;
wp.length = sizeof(wp);
GetWindowPlacement(&wp);
CSize size(evParam1);
m_fAudioOnly = (size.cx <= 0 || size.cy <= 0);
if(AfxGetAppSettings().fRememberZoomLevel
&& !(m_fFullScreen || wp.showCmd == SW_SHOWMAXIMIZED || wp.showCmd == SW_SHOWMINIMIZED))
{
ZoomVideoWindow();
}
else
{
MoveVideoWindow();
}
if(m_iMediaLoadState == MLS_LOADED
&& !m_fAudioOnly && (AfxGetAppSettings().nCLSwitches&CLSW_FULLSCREEN))
{
PostMessage(WM_COMMAND, ID_VIEW_FULLSCREEN);
AfxGetAppSettings().nCLSwitches &= ~CLSW_FULLSCREEN;
}
}
else if(EC_LENGTH_CHANGED == evCode)
{
__int64 rtDur = 0;
pMS->GetDuration(&rtDur);
m_wndPlaylistBar.SetCurTime(rtDur);
}
else if(!m_fCustomGraph)
{
TRACE(_T("evCode: %d\n"), evCode);
}
else if(EC_BG_AUDIO_CHANGED == evCode)
{
int nAudioChannels = evParam1;
m_wndStatusBar.SetStatusBitmap(nAudioChannels == 1 ? IDB_MONO
: nAudioChannels >= 2 ? IDB_STEREO
: IDB_NOAUDIO);
}
else if(EC_BG_ERROR == evCode)
{
SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
m_closingmsg = !str.IsEmpty() ? str : _T("Unspecified graph error");
m_wndPlaylistBar.SetCurValid(false);
break;
}
}
return hr;
}
LRESULT CMainFrame::OnRepaintRenderLess(WPARAM wParam, LPARAM lParam)
{
MoveVideoWindow();
return TRUE;
}
LRESULT CMainFrame::OnResumeFromState(WPARAM wParam, LPARAM lParam)
{
int iPlaybackMode = (int)wParam;
if(iPlaybackMode == PM_FILE)
{
SeekTo(10000i64*int(lParam));
}
else if(iPlaybackMode == PM_DVD)
{
CComPtr<IDvdState> pDvdState;
pDvdState.Attach((IDvdState*)lParam);
if(pDVDC) pDVDC->SetState(pDvdState, DVD_CMD_FLAG_Block, NULL);
}
else if(iPlaybackMode == PM_CAPTURE)
{
// not implemented
}
else
{
ASSERT(0);
return FALSE;
}
return TRUE;
}
BOOL CMainFrame::OnButton(UINT id, UINT nFlags, CPoint point)
{
SetFocus();
CRect r;
m_wndView.GetClientRect(r);
m_wndView.MapWindowPoints(this, &r);
if(id != wmcmd::WDOWN && id != wmcmd::WUP && !r.PtInRect(point)) return FALSE;
BOOL ret = FALSE;
AppSettings& s = AfxGetAppSettings();
POSITION pos = s.wmcmds.GetHeadPosition();
while(pos)
{
wmcmd& wc = s.wmcmds.GetNext(pos);
if(wc.mouse == id)
{
SendMessage(WM_COMMAND, wc.cmd);
ret = true;
}
}
return ret;
}
static bool s_fLDown = false;
void CMainFrame::OnLButtonDown(UINT nFlags, CPoint point)
{
SetFocus();
bool fClicked = false;
if(m_iPlaybackMode == PM_DVD)
{
CPoint p = point - m_wndView.GetVideoRect().TopLeft();
if(SUCCEEDED(pDVDC->ActivateAtPosition(p))
|| m_iDVDDomain == DVD_DOMAIN_VideoManagerMenu
|| m_iDVDDomain == DVD_DOMAIN_VideoTitleSetMenu)
fClicked = true;
}
if(!fClicked)
{
bool fLeftMouseBtnUnassigned = true;
AppSettings& s = AfxGetAppSettings();
POSITION pos = s.wmcmds.GetHeadPosition();
while(pos && fLeftMouseBtnUnassigned)
if(s.wmcmds.GetNext(pos).mouse == wmcmd::LDOWN)
fLeftMouseBtnUnassigned = false;
if(!m_fFullScreen && (IsCaptionMenuHidden() || fLeftMouseBtnUnassigned))
{
PostMessage(WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(point.x, point.y));
}
else
{
s_fLDown = true;
if(OnButton(wmcmd::LDOWN, nFlags, point))
return;
}
}
__super::OnLButtonDown(nFlags, point);
}
void CMainFrame::OnLButtonUp(UINT nFlags, CPoint point)
{
if(!OnButton(wmcmd::LUP, nFlags, point))
__super::OnLButtonUp(nFlags, point);
}
void CMainFrame::OnLButtonDblClk(UINT nFlags, CPoint point)
{
if(s_fLDown)
{
SendMessage(WM_LBUTTONDOWN, nFlags, MAKELPARAM(point.x, point.y));
s_fLDown = false;
}
if(!OnButton(wmcmd::LDBLCLK, nFlags, point))
__super::OnLButtonDblClk(nFlags, point);
}
void CMainFrame::OnMButtonDown(UINT nFlags, CPoint point)
{
SendMessage(WM_CANCELMODE);
if(!OnButton(wmcmd::MDOWN, nFlags, point))
__super::OnMButtonDown(nFlags, point);
}
void CMainFrame::OnMButtonUp(UINT nFlags, CPoint point)
{
if(!OnButton(wmcmd::MUP, nFlags, point))
__super::OnMButtonUp(nFlags, point);
}
void CMainFrame::OnMButtonDblClk(UINT nFlags, CPoint point)
{
SendMessage(WM_MBUTTONDOWN, nFlags, MAKELPARAM(point.x, point.y));
if(!OnButton(wmcmd::MDBLCLK, nFlags, point))
__super::OnMButtonDblClk(nFlags, point);
}
void CMainFrame::OnRButtonDown(UINT nFlags, CPoint point)
{
if(!OnButton(wmcmd::RDOWN, nFlags, point))
__super::OnRButtonDown(nFlags, point);
}
void CMainFrame::OnRButtonUp(UINT nFlags, CPoint point)
{
if(!OnButton(wmcmd::RUP, nFlags, point))
__super::OnRButtonUp(nFlags, point);
}
void CMainFrame::OnRButtonDblClk(UINT nFlags, CPoint point)
{
SendMessage(WM_RBUTTONDOWN, nFlags, MAKELPARAM(point.x, point.y));
if(!OnButton(wmcmd::RDBLCLK, nFlags, point))
__super::OnRButtonDblClk(nFlags, point);
}
LRESULT CMainFrame::OnXButtonDown(WPARAM wParam, LPARAM lParam)
{
SendMessage(WM_CANCELMODE);
UINT fwButton = GET_XBUTTON_WPARAM(wParam);
return OnButton(fwButton == XBUTTON1 ? wmcmd::X1DOWN : fwButton == XBUTTON2 ? wmcmd::X2DOWN : wmcmd::NONE,
GET_KEYSTATE_WPARAM(wParam), CPoint(lParam));
}
LRESULT CMainFrame::OnXButtonUp(WPARAM wParam, LPARAM lParam)
{
UINT fwButton = GET_XBUTTON_WPARAM(wParam);
return OnButton(fwButton == XBUTTON1 ? wmcmd::X1UP : fwButton == XBUTTON2 ? wmcmd::X2UP : wmcmd::NONE,
GET_KEYSTATE_WPARAM(wParam), CPoint(lParam));
}
LRESULT CMainFrame::OnXButtonDblClk(WPARAM wParam, LPARAM lParam)
{
SendMessage(WM_XBUTTONDOWN, wParam, lParam);
UINT fwButton = GET_XBUTTON_WPARAM(wParam);
return OnButton(fwButton == XBUTTON1 ? wmcmd::X1DBLCLK : fwButton == XBUTTON2 ? wmcmd::X2DBLCLK : wmcmd::NONE,
GET_KEYSTATE_WPARAM(wParam), CPoint(lParam));
}
BOOL CMainFrame::OnMouseWheel(UINT nFlags, short zDelta, CPoint point)
{
ScreenToClient(&point);
BOOL fRet =
zDelta > 0 ? OnButton(wmcmd::WUP, nFlags, point) :
zDelta < 0 ? OnButton(wmcmd::WDOWN, nFlags, point) :
FALSE;
return fRet;
}
void CMainFrame::OnMouseMove(UINT nFlags, CPoint point)
{
if(m_iPlaybackMode == PM_DVD)
{
CPoint vp = point - m_wndView.GetVideoRect().TopLeft();
pDVDC->SelectAtPosition(vp);
}
CSize diff = m_lastMouseMove - point;
if(m_fFullScreen && (abs(diff.cx)+abs(diff.cy)) >= 1)
{
int nTimeOut = AfxGetAppSettings().nShowBarsWhenFullScreenTimeOut;
if(nTimeOut < 0)
{
m_fHideCursor = false;
if(AfxGetAppSettings().fShowBarsWhenFullScreen)
ShowControls(AfxGetAppSettings().nCS);
KillTimer(TIMER_FULLSCREENCONTROLBARHIDER);
SetTimer(TIMER_FULLSCREENMOUSEHIDER, 2000, NULL);
}
else if(nTimeOut == 0)
{
CRect r;
GetClientRect(r);
r.top = r.bottom;
POSITION pos = m_bars.GetHeadPosition();
for(int i = 1; pos; i <<= 1)
{
CControlBar* pNext = m_bars.GetNext(pos);
CSize s = pNext->CalcFixedLayout(FALSE, TRUE);
if(AfxGetAppSettings().nCS&i) r.top -= s.cy;
}
// HACK: the controls would cover the menu too early hiding some buttons
if(m_iPlaybackMode == PM_DVD
&& (m_iDVDDomain == DVD_DOMAIN_VideoManagerMenu
|| m_iDVDDomain == DVD_DOMAIN_VideoTitleSetMenu))
r.top = r.bottom - 10;
m_fHideCursor = false;
if(r.PtInRect(point))
{
if(AfxGetAppSettings().fShowBarsWhenFullScreen)
ShowControls(AfxGetAppSettings().nCS);
}
else
{
if(AfxGetAppSettings().fShowBarsWhenFullScreen)
ShowControls(CS_NONE, false);
}
SetTimer(TIMER_FULLSCREENMOUSEHIDER, 2000, NULL);
}
else
{
m_fHideCursor = false;
if(AfxGetAppSettings().fShowBarsWhenFullScreen)
ShowControls(AfxGetAppSettings().nCS);
SetTimer(TIMER_FULLSCREENCONTROLBARHIDER, nTimeOut*1000, NULL);
SetTimer(TIMER_FULLSCREENMOUSEHIDER, max(nTimeOut*1000, 2000), NULL);
}
}
m_lastMouseMove = point;
__super::OnMouseMove(nFlags, point);
}
LRESULT CMainFrame::OnNcHitTest(CPoint point)
{
LRESULT nHitTest = __super::OnNcHitTest(point);
return ((IsCaptionMenuHidden()) && nHitTest == HTCLIENT) ? HTCAPTION : nHitTest;
}
void CMainFrame::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
if(pScrollBar->IsKindOf(RUNTIME_CLASS(CVolumeCtrl)))
{
OnPlayVolume(0);
}
else if(pScrollBar->IsKindOf(RUNTIME_CLASS(CPlayerSeekBar)) && m_iMediaLoadState == MLS_LOADED)
{
SeekTo(m_wndSeekBar.GetPos(), !!(::GetKeyState(VK_SHIFT)&0x8000));
}
__super::OnHScroll(nSBCode, nPos, pScrollBar);
}
void CMainFrame::OnInitMenu(CMenu* pMenu)
{
__super::OnInitMenu(pMenu);
MENUITEMINFO mii;
mii.cbSize = sizeof(mii);
for(UINT i = 0, j = pMenu->GetMenuItemCount(); i < j; i++)
{
CString str;
pMenu->GetMenuString(i, str, MF_BYPOSITION);
CMenu* pSubMenu = NULL;
if(str == ResStr(IDS_FAVORITES_POPUP))
{
SetupFavoritesSubMenu();
pSubMenu = &m_favorites;
}
if(pSubMenu)
{
mii.fMask = MIIM_STATE|MIIM_SUBMENU;
mii.fType = MF_POPUP;
mii.hSubMenu = pSubMenu->m_hMenu;
mii.fState = (pSubMenu->GetMenuItemCount() > 0 ? MF_ENABLED : (MF_DISABLED|MF_GRAYED));
pMenu->SetMenuItemInfo(i, &mii, TRUE);
}
}
}
void CMainFrame::OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu)
{
__super::OnInitMenuPopup(pPopupMenu, nIndex, bSysMenu);
static CAtlStringMap<UINT> transl;
if(transl.IsEmpty())
{
transl[_T("Navigate")] = IDS_NAVIGATE_POPUP;
transl[_T("Open Disc")] = IDS_OPENCDROM_POPUP;
transl[_T("Filters")] = IDS_FILTERS_POPUP;
transl[_T("Audio")] = IDS_AUDIO_POPUP;
transl[_T("Subtitles")] = IDS_SUBTITLES_POPUP;
transl[_T("Audio Language")] = IDS_AUDIOLANGUAGE_POPUP;
transl[_T("Subtitle Language")] = IDS_SUBTITLELANGUAGE_POPUP;
transl[_T("Video Angle")] = IDS_VIDEOANGLE_POPUP;
transl[_T("Jump To...")] = IDS_JUMPTO_POPUP;
transl[_T("Favorites")] = IDS_FAVORITES_POPUP;
transl[_T("Shaders")] = IDS_SHADER_POPUP;
transl[_T("Video Frame")] = IDS_VIDEOFRAME_POPUP;
transl[_T("PanScan")] = IDS_PANSCAN_POPUP;
transl[_T("Aspect Ratio")] = IDS_ASPECTRATIO_POPUP;
transl[_T("Zoom")] = IDS_ZOOM_POPUP;
}
MENUITEMINFO mii;
mii.cbSize = sizeof(mii);
for(UINT i = 0, j = pPopupMenu->GetMenuItemCount(); i < j; i++)
{
CString str;
pPopupMenu->GetMenuString(i, str, MF_BYPOSITION);
CString lookupstr = str;
lookupstr.Remove('&');
CMenu* pSubMenu = NULL;
UINT id;
if(transl.Lookup(lookupstr, id))
{
str = ResStr(id);
// pPopupMenu->ModifyMenu(i, MF_BYPOSITION|MF_STRING, 0, str);
MENUITEMINFO mii;
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_STRING;
mii.dwTypeData = (LPTSTR)(LPCTSTR)str;
pPopupMenu->SetMenuItemInfo(i, &mii, TRUE);
}
if(str == ResStr(IDS_NAVIGATE_POPUP))
{
UINT fState = (m_iMediaLoadState == MLS_LOADED
&& (1/*m_iPlaybackMode == PM_DVD *//*|| (m_iPlaybackMode == PM_FILE && m_PlayList.GetCount() > 0)*/))
? MF_ENABLED
: (MF_DISABLED|MF_GRAYED);
pPopupMenu->EnableMenuItem(i, MF_BYPOSITION|fState);
}
else if(str == ResStr(IDS_VIDEOFRAME_POPUP)
|| str == ResStr(IDS_PANSCAN_POPUP)
|| str == ResStr(IDS_ASPECTRATIO_POPUP)
|| str == ResStr(IDS_ZOOM_POPUP))
{
UINT fState = (m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly)
? MF_ENABLED
: (MF_DISABLED|MF_GRAYED);
pPopupMenu->EnableMenuItem(i, MF_BYPOSITION|fState);
}
else if(str == ResStr(IDS_OPENCDROM_POPUP))
{
SetupOpenCDSubMenu();
pSubMenu = &m_opencds;
}
else if(str == ResStr(IDS_FILTERS_POPUP))
{
SetupFiltersSubMenu();
pSubMenu = &m_filters;
}
else if(str == ResStr(IDS_AUDIO_POPUP))
{
SetupAudioSwitcherSubMenu();
pSubMenu = &m_audios;
}
else if(str == ResStr(IDS_SUBTITLES_POPUP))
{
SetupSubtitlesSubMenu();
pSubMenu = &m_subtitles;
}
else if(str == ResStr(IDS_AUDIOLANGUAGE_POPUP))
{
SetupNavAudioSubMenu();
pSubMenu = &m_navaudio;
}
else if(str == ResStr(IDS_SUBTITLELANGUAGE_POPUP))
{
SetupNavSubtitleSubMenu();
pSubMenu = &m_navsubtitle;
}
else if(str == ResStr(IDS_VIDEOANGLE_POPUP))
{
SetupNavAngleSubMenu();
pSubMenu = &m_navangle;
}
else if(str == ResStr(IDS_JUMPTO_POPUP))
{
SetupNavChaptersSubMenu();
pSubMenu = &m_navchapters;
}
else if(str == ResStr(IDS_FAVORITES_POPUP))
{
SetupFavoritesSubMenu();
pSubMenu = &m_favorites;
}
else if(str == ResStr(IDS_SHADER_POPUP))
{
SetupShadersSubMenu();
pSubMenu = &m_shaders;
}
if(pSubMenu)
{
mii.fMask = MIIM_STATE|MIIM_SUBMENU;
mii.fType = MF_POPUP;
mii.hSubMenu = pSubMenu->m_hMenu;
mii.fState = (pSubMenu->GetMenuItemCount() > 0 ? MF_ENABLED : (MF_DISABLED|MF_GRAYED));
pPopupMenu->SetMenuItemInfo(i, &mii, TRUE);
}
}
//
for(UINT i = 0, j = pPopupMenu->GetMenuItemCount(); i < j; i++)
{
UINT nID = pPopupMenu->GetMenuItemID(i);
if(nID == ID_SEPARATOR || nID == -1
|| nID >= ID_FAVORITES_FILE_START && nID <= ID_FAVORITES_FILE_END
|| nID >= ID_NAVIGATE_CHAP_SUBITEM_START && nID <= ID_NAVIGATE_CHAP_SUBITEM_END)
continue;
CString str;
pPopupMenu->GetMenuString(i, str, MF_BYPOSITION);
int k = str.Find('\t');
if(k > 0) str = str.Left(k);
CString key = CPPageAccelTbl::MakeAccelShortcutLabel(nID);
if(!key.IsEmpty()) str += _T("\t") + key;
if(key.IsEmpty() && i < 0) continue;
// BUG(?): this disables menu item update ui calls for some reason...
// pPopupMenu->ModifyMenu(i, MF_BYPOSITION|MF_STRING, nID, str);
// this works fine
MENUITEMINFO mii;
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_STRING;
mii.dwTypeData = (LPTSTR)(LPCTSTR)str;
pPopupMenu->SetMenuItemInfo(i, &mii, TRUE);
}
//
bool fPnSPresets = false;
for(UINT i = 0, j = pPopupMenu->GetMenuItemCount(); i < j; i++)
{
UINT nID = pPopupMenu->GetMenuItemID(i);
if(nID >= ID_PANNSCAN_PRESETS_START && nID < ID_PANNSCAN_PRESETS_END)
{
do
{
nID = pPopupMenu->GetMenuItemID(i);
pPopupMenu->DeleteMenu(i, MF_BYPOSITION);
j--;
}
while(i < j && nID >= ID_PANNSCAN_PRESETS_START && nID < ID_PANNSCAN_PRESETS_END);
nID = pPopupMenu->GetMenuItemID(i);
}
if(nID == ID_VIEW_RESET)
{
fPnSPresets = true;
}
}
if(fPnSPresets)
{
AppSettings& s = AfxGetAppSettings();
int i = 0, j = s.m_pnspresets.GetCount();
for(; i < j; i++)
{
int k = 0;
CString label = s.m_pnspresets[i].Tokenize(_T(","), k);
pPopupMenu->InsertMenu(ID_VIEW_RESET, MF_BYCOMMAND, ID_PANNSCAN_PRESETS_START+i, label);
}
// if(j > 0)
{
pPopupMenu->InsertMenu(ID_VIEW_RESET, MF_BYCOMMAND, ID_PANNSCAN_PRESETS_START+i, ResStr(IDS_PANSCAN_EDIT));
pPopupMenu->InsertMenu(ID_VIEW_RESET, MF_BYCOMMAND|MF_SEPARATOR);
}
}
}
BOOL CMainFrame::OnMenu(CMenu* pMenu)
{
if(!pMenu) return FALSE;
KillTimer(TIMER_FULLSCREENMOUSEHIDER);
m_fHideCursor = false;
CPoint point;
GetCursorPos(&point);
pMenu->TrackPopupMenu(TPM_RIGHTBUTTON|TPM_NOANIMATION, point.x+1, point.y+1, this);
return TRUE;
}
void CMainFrame::OnMenuPlayerShort()
{
if(IsCaptionMenuHidden())
{
OnMenu(m_popupmain.GetSubMenu(0));
}
else
{
OnMenu(m_popup.GetSubMenu(0));
}
}
void CMainFrame::OnMenuPlayerLong()
{
OnMenu(m_popupmain.GetSubMenu(0));
}
void CMainFrame::OnMenuFilters()
{
SetupFiltersSubMenu();
OnMenu(&m_filters);
}
void CMainFrame::OnUpdatePlayerStatus(CCmdUI* pCmdUI)
{
if(m_iMediaLoadState == MLS_LOADING)
{
pCmdUI->SetText(ResStr(IDS_CONTROLS_OPENING));
}
else if(m_iMediaLoadState == MLS_LOADED)
{
CString msg;
if(!m_playingmsg.IsEmpty())
{
msg = m_playingmsg;
}
else if(m_fCapturing)
{
msg = ResStr(IDS_CONTROLS_CAPTURING);
if(pAMDF)
{
long lDropped = 0;
pAMDF->GetNumDropped(&lDropped);
long lNotDropped = 0;
pAMDF->GetNumNotDropped(&lNotDropped);
if((lDropped + lNotDropped) > 0)
{
CString str;
str.Format(_T(", Total: %d, Dropped: %d"), lDropped + lNotDropped, lDropped);
msg += str;
}
}
CComPtr<IPin> pPin;
if(SUCCEEDED(pCGB->FindPin(m_wndCaptureBar.m_capdlg.m_pDst, PINDIR_INPUT, NULL, NULL, FALSE, 0, &pPin)))
{
LONGLONG size = 0;
if(CComQIPtr<IStream> pStream = pPin)
{
pStream->Commit(STGC_DEFAULT);
WIN32_FIND_DATA findFileData;
HANDLE h = FindFirstFile(m_wndCaptureBar.m_capdlg.m_file, &findFileData);
if(h != INVALID_HANDLE_VALUE)
{
size = ((LONGLONG)findFileData.nFileSizeHigh << 32) | findFileData.nFileSizeLow;
CString str;
if(size < 1024i64*1024)
str.Format(_T(", Size: %I64dKB"), size/1024);
else //if(size < 1024i64*1024*1024)
str.Format(_T(", Size: %I64dMB"), size/1024/1024);
msg += str;
FindClose(h);
}
}
ULARGE_INTEGER FreeBytesAvailable, TotalNumberOfBytes, TotalNumberOfFreeBytes;
if(GetDiskFreeSpaceEx(
m_wndCaptureBar.m_capdlg.m_file.Left(m_wndCaptureBar.m_capdlg.m_file.ReverseFind('\\')+1),
&FreeBytesAvailable, &TotalNumberOfBytes, &TotalNumberOfFreeBytes))
{
CString str;
if(FreeBytesAvailable.QuadPart < 1024i64*1024)
str.Format(_T(", Free: %I64dKB"), FreeBytesAvailable.QuadPart/1024);
else //if(FreeBytesAvailable.QuadPart < 1024i64*1024*1024)
str.Format(_T(", Free: %I64dMB"), FreeBytesAvailable.QuadPart/1024/1024);
msg += str;
}
if(m_wndCaptureBar.m_capdlg.m_pMux)
{
__int64 pos = 0;
CComQIPtr<IMediaSeeking> pMuxMS = m_wndCaptureBar.m_capdlg.m_pMux;
if(pMuxMS && SUCCEEDED(pMuxMS->GetCurrentPosition(&pos)) && pos > 0)
{
double bytepersec = 10000000.0 * size / pos;
if(bytepersec > 0)
m_rtDurationOverride = __int64(10000000.0 * (FreeBytesAvailable.QuadPart+size) / bytepersec);
}
}
if(m_wndCaptureBar.m_capdlg.m_pVidBuffer
|| m_wndCaptureBar.m_capdlg.m_pAudBuffer)
{
int nFreeVidBuffers = 0, nFreeAudBuffers = 0;
if(CComQIPtr<IBufferFilter> pVB = m_wndCaptureBar.m_capdlg.m_pVidBuffer)
nFreeVidBuffers = pVB->GetFreeBuffers();
if(CComQIPtr<IBufferFilter> pAB = m_wndCaptureBar.m_capdlg.m_pAudBuffer)
nFreeAudBuffers = pAB->GetFreeBuffers();
CString str;
str.Format(_T(", Free V/A Buffers: %03d/%03d"), nFreeVidBuffers, nFreeAudBuffers);
msg += str;
}
}
}
else if(m_fBuffering)
{
BeginEnumFilters(pGB, pEF, pBF)
{
if(CComQIPtr<IAMNetworkStatus, &IID_IAMNetworkStatus> pAMNS = pBF)
{
long BufferingProgress = 0;
if(SUCCEEDED(pAMNS->get_BufferingProgress(&BufferingProgress)) && BufferingProgress > 0)
{
msg.Format(ResStr(IDS_CONTROLS_BUFFERING), BufferingProgress);
__int64 start = 0, stop = 0;
m_wndSeekBar.GetRange(start, stop);
m_fLiveWM = (stop == start);
}
break;
}
}
EndEnumFilters
}
else if(pAMOP)
{
__int64 t = 0, c = 0;
if(SUCCEEDED(pAMOP->QueryProgress(&t, &c)) && t > 0 && c < t)
msg.Format(ResStr(IDS_CONTROLS_BUFFERING), c*100/t);
if(m_fUpdateInfoBar)
OpenSetupInfoBar();
}
OAFilterState fs = GetMediaState();
pCmdUI->SetText(
!msg.IsEmpty() ? msg :
fs == State_Stopped ? ResStr(IDS_CONTROLS_STOPPED) :
(fs == State_Paused || m_fFrameSteppingActive) ? ResStr(IDS_CONTROLS_PAUSED) :
fs == State_Running ? ResStr(IDS_CONTROLS_PLAYING) :
_T(""));
}
else if(m_iMediaLoadState == MLS_CLOSING)
{
pCmdUI->SetText(ResStr(IDS_CONTROLS_CLOSING));
}
else
{
pCmdUI->SetText(m_closingmsg);
}
}
void CMainFrame::OnFilePostOpenmedia()
{
OpenSetupInfoBar();
OpenSetupStatsBar();
OpenSetupStatusBar();
// OpenSetupToolBar();
OpenSetupCaptureBar();
__int64 rtDur = 0;
pMS->GetDuration(&rtDur);
m_wndPlaylistBar.SetCurTime(rtDur);
if(m_iPlaybackMode == PM_CAPTURE)
{
ShowControlBar(&m_wndSubresyncBar, FALSE, TRUE);
// ShowControlBar(&m_wndPlaylistBar, FALSE, TRUE);
// ShowControlBar(&m_wndCaptureBar, TRUE, TRUE);
}
m_iMediaLoadState = MLS_LOADED;
// IMPORTANT: must not call any windowing msgs before
// this point, it will deadlock when OpenMediaPrivate is
// still running and the renderer window was created on
// the same worker-thread
{
WINDOWPLACEMENT wp;
wp.length = sizeof(wp);
GetWindowPlacement(&wp);
// restore magnification
if(IsWindowVisible() && AfxGetAppSettings().fRememberZoomLevel
&& !(m_fFullScreen || wp.showCmd == SW_SHOWMAXIMIZED || wp.showCmd == SW_SHOWMINIMIZED))
{
ZoomVideoWindow();
}
}
if(!m_fAudioOnly && (AfxGetAppSettings().nCLSwitches&CLSW_FULLSCREEN))
{
SendMessage(WM_COMMAND, ID_VIEW_FULLSCREEN);
AfxGetAppSettings().nCLSwitches &= ~CLSW_FULLSCREEN;
}
SendNowPlayingToMSN();
SendNowPlayingTomIRC();
}
void CMainFrame::OnUpdateFilePostOpenmedia(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_iMediaLoadState == MLS_LOADING);
}
void CMainFrame::OnFilePostClosemedia()
{
m_wndView.SetVideoRect();
m_wndSeekBar.Enable(false);
m_wndSeekBar.SetPos(0);
m_wndInfoBar.RemoveAllLines();
m_wndStatsBar.RemoveAllLines();
m_wndStatusBar.Clear();
m_wndStatusBar.ShowTimer(false);
if(IsWindow(m_wndSubresyncBar.m_hWnd))
{
ShowControlBar(&m_wndSubresyncBar, FALSE, TRUE);
SetSubtitle(NULL);
}
if(IsWindow(m_wndCaptureBar.m_hWnd))
{
ShowControlBar(&m_wndCaptureBar, FALSE, TRUE);
m_wndCaptureBar.m_capdlg.SetupVideoControls(_T(""), NULL, NULL, NULL);
m_wndCaptureBar.m_capdlg.SetupAudioControls(_T(""), NULL, CInterfaceArray<IAMAudioInputMixer>());
}
RecalcLayout();
SetWindowText(ResStr(IDR_MAINFRAME));
SetAlwaysOnTop(AfxGetAppSettings().iOnTop);
// this will prevent any further UI updates on the dynamically added menu items
SetupFiltersSubMenu();
SetupAudioSwitcherSubMenu();
SetupSubtitlesSubMenu();
SetupNavAudioSubMenu();
SetupNavSubtitleSubMenu();
SetupNavAngleSubMenu();
SetupNavChaptersSubMenu();
SetupFavoritesSubMenu();
SendNowPlayingToMSN();
}
void CMainFrame::OnUpdateFilePostClosemedia(CCmdUI* pCmdUI)
{
pCmdUI->Enable(!!m_hWnd && m_iMediaLoadState == MLS_CLOSING);
}
void CMainFrame::OnBossKey()
{
SendMessage(WM_COMMAND, ID_PLAY_PAUSE);
if(m_fFullScreen) SendMessage(WM_COMMAND, ID_VIEW_FULLSCREEN);
SendMessage(WM_SYSCOMMAND, SC_MINIMIZE, -1);
}
void CMainFrame::OnStreamAudio(UINT nID)
{
nID -= ID_STREAM_AUDIO_NEXT;
if(m_iMediaLoadState != MLS_LOADED) return;
CComQIPtr<IAMStreamSelect> pSS = FindFilter(__uuidof(CAudioSwitcherFilter), pGB);
if(!pSS) pSS = FindFilter(L"{D3CD7858-971A-4838-ACEC-40CA5D529DC8}", pGB); // morgan's switcher
DWORD cStreams = 0;
if(pSS && SUCCEEDED(pSS->Count(&cStreams)) && cStreams > 1)
{
for(int i = 0; i < (int)cStreams; i++)
{
AM_MEDIA_TYPE* pmt = NULL;
DWORD dwFlags = 0;
LCID lcid = 0;
DWORD dwGroup = 0;
WCHAR* pszName = NULL;
if(FAILED(pSS->Info(i, &pmt, &dwFlags, &lcid, &dwGroup, &pszName, NULL, NULL)))
return;
if(pmt) DeleteMediaType(pmt);
if(pszName) CoTaskMemFree(pszName);
if(dwFlags&(AMSTREAMSELECTINFO_ENABLED|AMSTREAMSELECTINFO_EXCLUSIVE))
{
pSS->Enable((i+(nID==0?1:cStreams-1))%cStreams, AMSTREAMSELECTENABLE_ENABLE);
break;
}
}
}
else if(m_iPlaybackMode == PM_FILE) SendMessage(WM_COMMAND, ID_OGM_AUDIO_NEXT+nID);
else if(m_iPlaybackMode == PM_DVD) SendMessage(WM_COMMAND, ID_DVD_AUDIO_NEXT+nID);
}
void CMainFrame::OnStreamSub(UINT nID)
{
nID -= ID_STREAM_SUB_NEXT;
if(m_iMediaLoadState != MLS_LOADED) return;
int cnt = 0;
POSITION pos = m_pSubStreams.GetHeadPosition();
while(pos) cnt += m_pSubStreams.GetNext(pos)->GetStreamCount();
if(cnt > 1)
{
int i = ((m_iSubtitleSel&0x7fffffff)+(nID==0?1:cnt-1))%cnt;
m_iSubtitleSel = i | (m_iSubtitleSel&0x80000000);
UpdateSubtitle();
SetFocus();
}
else if(m_iPlaybackMode == PM_FILE) SendMessage(WM_COMMAND, ID_OGM_SUB_NEXT+nID);
else if(m_iPlaybackMode == PM_DVD) SendMessage(WM_COMMAND, ID_DVD_SUB_NEXT+nID);
}
void CMainFrame::OnStreamSubOnOff()
{
if(m_iMediaLoadState != MLS_LOADED) return;
int cnt = 0;
POSITION pos = m_pSubStreams.GetHeadPosition();
while(pos) cnt += m_pSubStreams.GetNext(pos)->GetStreamCount();
if(cnt > 0)
{
m_iSubtitleSel ^= 0x80000000;
UpdateSubtitle();
SetFocus();
}
else if(m_iPlaybackMode == PM_DVD) SendMessage(WM_COMMAND, ID_DVD_SUB_ONOFF);
}
void CMainFrame::OnOgmAudio(UINT nID)
{
nID -= ID_OGM_AUDIO_NEXT;
if(m_iMediaLoadState != MLS_LOADED) return;
CComQIPtr<IAMStreamSelect> pSS = FindFilter(CLSID_OggSplitter, pGB);
if(!pSS) pSS = FindFilter(L"{55DA30FC-F16B-49fc-BAA5-AE59FC65F82D}", pGB);
if(!pSS) return;
CAtlArray<int> snds;
int iSel = -1;
DWORD cStreams = 0;
if(SUCCEEDED(pSS->Count(&cStreams)) && cStreams > 1)
{
for(int i = 0; i < (int)cStreams; i++)
{
AM_MEDIA_TYPE* pmt = NULL;
DWORD dwFlags = 0;
LCID lcid = 0;
DWORD dwGroup = 0;
WCHAR* pszName = NULL;
if(FAILED(pSS->Info(i, &pmt, &dwFlags, &lcid, &dwGroup, &pszName, NULL, NULL)))
return;
if(dwGroup == 1)
{
if(dwFlags&(AMSTREAMSELECTINFO_ENABLED|AMSTREAMSELECTINFO_EXCLUSIVE))
iSel = snds.GetCount();
snds.Add(i);
}
if(pmt) DeleteMediaType(pmt);
if(pszName) CoTaskMemFree(pszName);
}
int cnt = snds.GetCount();
if(cnt > 1 && iSel >= 0)
pSS->Enable(snds[(iSel+(nID==0?1:cnt-1))%cnt], AMSTREAMSELECTENABLE_ENABLE);
}
}
void CMainFrame::OnOgmSub(UINT nID)
{
nID -= ID_OGM_SUB_NEXT;
if(m_iMediaLoadState != MLS_LOADED) return;
CComQIPtr<IAMStreamSelect> pSS = FindFilter(CLSID_OggSplitter, pGB);
if(!pSS) pSS = FindFilter(L"{55DA30FC-F16B-49fc-BAA5-AE59FC65F82D}", pGB);
if(!pSS) return;
CAtlArray<int> subs;
int iSel = -1;
DWORD cStreams = 0;
if(SUCCEEDED(pSS->Count(&cStreams)) && cStreams > 1)
{
for(int i = 0; i < (int)cStreams; i++)
{
AM_MEDIA_TYPE* pmt = NULL;
DWORD dwFlags = 0;
LCID lcid = 0;
DWORD dwGroup = 0;
WCHAR* pszName = NULL;
if(FAILED(pSS->Info(i, &pmt, &dwFlags, &lcid, &dwGroup, &pszName, NULL, NULL)))
return;
if(dwGroup == 2)
{
if(dwFlags&(AMSTREAMSELECTINFO_ENABLED|AMSTREAMSELECTINFO_EXCLUSIVE))
iSel = subs.GetCount();
subs.Add(i);
}
if(pmt) DeleteMediaType(pmt);
if(pszName) CoTaskMemFree(pszName);
}
int cnt = subs.GetCount();
if(cnt > 1 && iSel >= 0)
pSS->Enable(subs[(iSel+(nID==0?1:cnt-1))%cnt], AMSTREAMSELECTENABLE_ENABLE);
}
}
void CMainFrame::OnDvdAngle(UINT nID)
{
nID -= ID_DVD_ANGLE_NEXT;
if(m_iMediaLoadState != MLS_LOADED) return;
if(pDVDI && pDVDC)
{
ULONG ulAnglesAvailable, ulCurrentAngle;
if(SUCCEEDED(pDVDI->GetCurrentAngle(&ulAnglesAvailable, &ulCurrentAngle)) && ulAnglesAvailable > 1)
{
ulCurrentAngle += nID==0 ? 1 : ulAnglesAvailable-1;
if(ulCurrentAngle > ulAnglesAvailable) ulCurrentAngle = 1;
else if(ulCurrentAngle < 1) ulCurrentAngle = ulAnglesAvailable;
pDVDC->SelectAngle(ulCurrentAngle, DVD_CMD_FLAG_Block, NULL);
}
}
}
void CMainFrame::OnDvdAudio(UINT nID)
{
nID -= ID_DVD_AUDIO_NEXT;
if(m_iMediaLoadState != MLS_LOADED) return;
if(pDVDI && pDVDC)
{
ULONG nStreamsAvailable, nCurrentStream;
if(SUCCEEDED(pDVDI->GetCurrentAudio(&nStreamsAvailable, &nCurrentStream)) && nStreamsAvailable > 1)
pDVDC->SelectAudioStream((nCurrentStream+(nID==0?1:nStreamsAvailable-1))%nStreamsAvailable, DVD_CMD_FLAG_Block, NULL);
}
}
void CMainFrame::OnDvdSub(UINT nID)
{
nID -= ID_DVD_SUB_NEXT;
if(m_iMediaLoadState != MLS_LOADED) return;
if(pDVDI && pDVDC)
{
ULONG ulStreamsAvailable, ulCurrentStream;
BOOL bIsDisabled;
if(SUCCEEDED(pDVDI->GetCurrentSubpicture(&ulStreamsAvailable, &ulCurrentStream, &bIsDisabled))
&& ulStreamsAvailable > 1)
{
pDVDC->SelectSubpictureStream(
(ulCurrentStream+(nID==0?1:ulStreamsAvailable-1))%ulStreamsAvailable,
DVD_CMD_FLAG_Block, NULL);
}
}
}
void CMainFrame::OnDvdSubOnOff()
{
if(m_iMediaLoadState != MLS_LOADED) return;
if(pDVDI && pDVDC)
{
ULONG ulStreamsAvailable, ulCurrentStream;
BOOL bIsDisabled;
if(SUCCEEDED(pDVDI->GetCurrentSubpicture(&ulStreamsAvailable, &ulCurrentStream, &bIsDisabled)))
{
pDVDC->SetSubpictureState(bIsDisabled, DVD_CMD_FLAG_Block, NULL);
}
}
}
//
// menu item handlers
//
// file
void CMainFrame::OnFileOpenQuick()
{
if(m_iMediaLoadState == MLS_LOADING || !IsWindow(m_wndPlaylistBar)) return;
CString filter;
CAtlArray<CString> mask;
AfxGetAppSettings().Formats.GetFilter(filter, mask);
COpenFileDlg fd(mask, true, NULL, NULL,
OFN_EXPLORER|OFN_ENABLESIZING|OFN_HIDEREADONLY|OFN_ALLOWMULTISELECT|OFN_ENABLEINCLUDENOTIFY,
filter, this);
if(fd.DoModal() != IDOK) return;
CAtlList<CString> fns;
POSITION pos = fd.GetStartPosition();
while(pos) fns.AddTail(fd.GetNextPathName(pos));
bool fMultipleFiles = false;
if(fns.GetCount() > 1
|| fns.GetCount() == 1
&& (fns.GetHead()[fns.GetHead().GetLength()-1] == '\\'
|| fns.GetHead()[fns.GetHead().GetLength()-1] == '*'))
{
fMultipleFiles = true;
}
SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
ShowWindow(SW_SHOW);
SetForegroundWindow();
m_wndPlaylistBar.Open(fns, fMultipleFiles);
if(m_wndPlaylistBar.GetCount() == 1 && m_wndPlaylistBar.IsWindowVisible() && !m_wndPlaylistBar.IsFloating())
{
ShowControlBar(&m_wndPlaylistBar, FALSE, TRUE);
}
OpenCurPlaylistItem();
}
void CMainFrame::OnFileOpenmedia()
{
if(m_iMediaLoadState == MLS_LOADING || !IsWindow(m_wndPlaylistBar)) return;
COpenDlg dlg;
if(dlg.DoModal() != IDOK || dlg.m_fns.GetCount() == 0) return;
if(dlg.m_fAppendPlaylist)
{
m_wndPlaylistBar.Append(dlg.m_fns, dlg.m_fMultipleFiles);
return;
}
SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
ShowWindow(SW_SHOW);
SetForegroundWindow();
m_wndPlaylistBar.Open(dlg.m_fns, dlg.m_fMultipleFiles);
if(m_wndPlaylistBar.GetCount() == 1 && m_wndPlaylistBar.IsWindowVisible() && !m_wndPlaylistBar.IsFloating())
{
ShowControlBar(&m_wndPlaylistBar, FALSE, TRUE);
}
OpenCurPlaylistItem();
}
void CMainFrame::OnUpdateFileOpen(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_iMediaLoadState != MLS_LOADING);
}
BOOL CMainFrame::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCDS)
{
if(m_iMediaLoadState == MLS_LOADING || !IsWindow(m_wndPlaylistBar))
return FALSE;
if(pCDS->dwData != 0x6ABE51 || pCDS->cbData < sizeof(DWORD))
return FALSE;
DWORD len = *((DWORD*)pCDS->lpData);
TCHAR* pBuff = (TCHAR*)((DWORD*)pCDS->lpData + 1);
TCHAR* pBuffEnd = (TCHAR*)((BYTE*)pBuff + pCDS->cbData - sizeof(DWORD));
CAtlList<CString> cmdln;
while(len-- > 0)
{
CString str;
while(pBuff < pBuffEnd && *pBuff) str += *pBuff++;
pBuff++;
cmdln.AddTail(str);
}
AppSettings& s = AfxGetAppSettings();
s.ParseCommandLine(cmdln);
POSITION pos = s.slFilters.GetHeadPosition();
while(pos)
{
CString fullpath = MakeFullPath(s.slFilters.GetNext(pos));
CPath tmp(fullpath);
tmp.RemoveFileSpec();
tmp.AddBackslash();
CString path = tmp;
WIN32_FIND_DATA fd = {0};
HANDLE hFind = FindFirstFile(fullpath, &fd);
if(hFind != INVALID_HANDLE_VALUE)
{
do
{
if(fd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) continue;
CFilterMapper2 fm2(false);
fm2.Register(path + fd.cFileName);
while(!fm2.m_filters.IsEmpty())
{
if(FilterOverride* f = fm2.m_filters.RemoveTail())
{
f->fTemporary = true;
bool fFound = false;
POSITION pos2 = s.filters.GetHeadPosition();
while(pos2)
{
FilterOverride* f2 = s.filters.GetNext(pos2);
if(f2->type == FilterOverride::EXTERNAL && !f2->path.CompareNoCase(f->path))
{
fFound = true;
break;
}
}
if(!fFound)
{
CAutoPtr<FilterOverride> p(f);
s.filters.AddHead(p);
}
}
}
}
while(FindNextFile(hFind, &fd));
FindClose(hFind);
}
}
bool fSetForegroundWindow = false;
if((s.nCLSwitches&CLSW_DVD) && !s.slFiles.IsEmpty())
{
SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
fSetForegroundWindow = true;
CAutoPtr<OpenDVDData> p(new OpenDVDData());
if(p) {p->path = s.slFiles.GetHead(); p->subs.AddTailList(&s.slSubs);}
OpenMedia(p);
}
else if(s.nCLSwitches&CLSW_CD)
{
SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
fSetForegroundWindow = true;
CAtlList<CString> sl;
if(!s.slFiles.IsEmpty())
{
GetCDROMType(s.slFiles.GetHead()[0], sl);
}
else
{
CString dir;
dir.ReleaseBufferSetLength(GetCurrentDirectory(MAX_PATH, dir.GetBuffer(MAX_PATH)));
GetCDROMType(dir[0], sl);
for(TCHAR drive = 'C'; sl.IsEmpty() && drive <= 'Z'; drive++)
{
GetCDROMType(drive, sl);
}
}
m_wndPlaylistBar.Open(sl, true);
OpenCurPlaylistItem();
}
else if(!s.slFiles.IsEmpty())
{
bool fMulti = s.slFiles.GetCount() > 1;
CAtlList<CString> sl;
sl.AddTailList(&s.slFiles);
if(!fMulti) sl.AddTailList(&s.slDubs);
if((s.nCLSwitches&CLSW_ADD) && m_wndPlaylistBar.GetCount() > 0)
{
m_wndPlaylistBar.Append(sl, fMulti, &s.slSubs);
if(s.nCLSwitches&(CLSW_OPEN|CLSW_PLAY))
{
m_wndPlaylistBar.SetLast();
OpenCurPlaylistItem();
}
}
else
{
SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
fSetForegroundWindow = true;
m_wndPlaylistBar.Open(sl, fMulti, &s.slSubs);
OpenCurPlaylistItem((s.nCLSwitches&CLSW_STARTVALID) ? s.rtStart : 0);
s.nCLSwitches &= ~CLSW_STARTVALID;
s.rtStart = 0;
}
}
else
{
s.nCLSwitches = CLSW_NONE;
}
if(fSetForegroundWindow && !(s.nCLSwitches&CLSW_NOFOCUS))
SetForegroundWindow();
s.nCLSwitches &= ~CLSW_NOFOCUS;
return TRUE;
}
void CMainFrame::OnFileOpendvd()
{
if(m_iMediaLoadState == MLS_LOADING) return;
SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
SetForegroundWindow();
ShowWindow(SW_SHOW);
CAutoPtr<OpenDVDData> p(new OpenDVDData());
if(p)
{
AppSettings& s = AfxGetAppSettings();
if(s.fUseDVDPath && !s.sDVDPath.IsEmpty())
{
p->path = s.sDVDPath;
p->path.Replace('/', '\\');
if(p->path[p->path.GetLength()-1] != '\\') p->path += '\\';
}
}
OpenMedia(p);
}
void CMainFrame::OnFileOpendevice()
{
if(m_iMediaLoadState == MLS_LOADING) return;
COpenCapDeviceDlg capdlg;
if(capdlg.DoModal() != IDOK)
return;
SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
SetForegroundWindow();
ShowWindow(SW_SHOW);
m_wndPlaylistBar.Empty();
CAutoPtr<OpenDeviceData> p(new OpenDeviceData());
if(p) {p->DisplayName[0] = capdlg.m_vidstr; p->DisplayName[1] = capdlg.m_audstr;}
OpenMedia(p);
}
void CMainFrame::OnFileOpenCD(UINT nID)
{
nID -= ID_FILE_OPEN_CD_START;
nID++;
for(TCHAR drive = 'C'; drive <= 'Z'; drive++)
{
CAtlList<CString> sl;
switch(GetCDROMType(drive, sl))
{
case CDROM_Audio:
case CDROM_VideoCD:
case CDROM_DVDVideo:
nID--;
break;
default:
break;
}
if(nID == 0)
{
SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
SetForegroundWindow();
ShowWindow(SW_SHOW);
m_wndPlaylistBar.Open(sl, true);
OpenCurPlaylistItem();
break;
}
}
}
void CMainFrame::OnDropFiles(HDROP hDropInfo)
{
SetForegroundWindow();
if(m_wndPlaylistBar.IsWindowVisible())
{
m_wndPlaylistBar.OnDropFiles(hDropInfo);
return;
}
CAtlList<CString> sl;
UINT nFiles = ::DragQueryFile(hDropInfo, (UINT)-1, NULL, 0);
for(UINT iFile = 0; iFile < nFiles; iFile++)
{
CString fn;
fn.ReleaseBuffer(::DragQueryFile(hDropInfo, iFile, fn.GetBuffer(MAX_PATH), MAX_PATH));
sl.AddTail(fn);
}
::DragFinish(hDropInfo);
if(sl.IsEmpty()) return;
if(sl.GetCount() == 1 && m_iMediaLoadState == MLS_LOADED && m_pCAP)
{
if(LoadSubtitle(sl.GetHead()))
{
SetSubtitle(m_pSubStreams.GetTail());
CPath p(sl.GetHead());
p.StripPath();
SendStatusMessage(CString((LPCTSTR)p) + _T(" loaded successfully"), 3000);
return;
}
}
m_wndPlaylistBar.Open(sl, true);
OpenCurPlaylistItem();
}
void CMainFrame::OnFileSaveAs()
{
CString ext, in = m_wndPlaylistBar.GetCur(), out = in;
if(out.Find(_T("://")) < 0)
{
ext = CString(CPath(out).GetExtension()).MakeLower();
if(ext == _T(".cda")) out = out.Left(out.GetLength()-4) + _T(".wav");
else if(ext == _T(".ifo")) out = out.Left(out.GetLength()-4) + _T(".vob");
}
else
{
out.Empty();
}
CFileDialog fd(FALSE, 0, out,
OFN_EXPLORER|OFN_ENABLESIZING|OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_PATHMUSTEXIST,
_T("All files (*.*)|*.*||"), this, 0);
if(fd.DoModal() != IDOK || !in.CompareNoCase(fd.GetPathName())) return;
CPath p(fd.GetPathName());
if(!ext.IsEmpty()) p.AddExtension(ext);
OAFilterState fs = State_Stopped;
pMC->GetState(0, &fs);
if(fs == State_Running) pMC->Pause();
CSaveDlg dlg(in, p);
dlg.DoModal();
if(fs == State_Running) pMC->Run();
}
void CMainFrame::OnUpdateFileSaveAs(CCmdUI* pCmdUI)
{
if(m_iMediaLoadState != MLS_LOADED || m_iPlaybackMode != PM_FILE)
{
pCmdUI->Enable(FALSE);
return;
}
CString fn = m_wndPlaylistBar.GetCur();
CString ext = fn.Mid(fn.ReverseFind('.')+1).MakeLower();
int i = fn.Find(_T("://"));
if(i >= 0)
{
CString protocol = fn.Left(i).MakeLower();
if(protocol != _T("http"))
{
pCmdUI->Enable(FALSE);
return;
}
}
if((GetVersion()&0x80000000) && (ext == _T("cda") || ext == _T("ifo")))
{
pCmdUI->Enable(FALSE);
return;
}
pCmdUI->Enable(TRUE);
}
bool CMainFrame::GetDIB(BYTE** ppData, long& size, bool fSilent)
{
if(!ppData) return false;
*ppData = NULL;
size = 0;
bool fNeedsToPause = !m_pCAP;
if(fNeedsToPause) fNeedsToPause = !IsVMR7InGraph(pGB);
if(fNeedsToPause) fNeedsToPause = !IsVMR9InGraph(pGB);
OAFilterState fs = GetMediaState();
if(!(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly && (fs == State_Paused || fs == State_Running)))
return false;
if(fs == State_Running && fNeedsToPause)
{
pMC->Pause();
GetMediaState(); // wait for completion of the pause command
}
HRESULT hr = S_OK;
CString errmsg;
do
{
if(m_pCAP)
{
hr = m_pCAP->GetDIB(NULL, (DWORD*)&size);
if(FAILED(hr)) {errmsg.Format(_T("GetDIB failed, hr = %08x"), hr); break;}
if(!(*ppData = new BYTE[size])) return false;
hr = m_pCAP->GetDIB(*ppData, (DWORD*)&size);
if(FAILED(hr)) {errmsg.Format(_T("GetDIB failed, hr = %08x"), hr); break;}
}
else
{
hr = pBV->GetCurrentImage(&size, NULL);
if(FAILED(hr) || size == 0) {errmsg.Format(_T("GetCurrentImage failed, hr = %08x"), hr); break;}
if(!(*ppData = new BYTE[size])) return false;
hr = pBV->GetCurrentImage(&size, (long*)*ppData);
if(FAILED(hr)) {errmsg.Format(_T("GetCurrentImage failed, hr = %08x"), hr); break;}
}
}
while(0);
if(!fSilent)
{
if(!errmsg.IsEmpty())
{
AfxMessageBox(errmsg, MB_OK);
}
}
if(fs == State_Running && GetMediaState() != State_Running)
{
pMC->Run();
}
if(FAILED(hr))
{
if(*ppData) {ASSERT(0); delete [] *ppData; *ppData = NULL;} // huh?
return false;
}
return true;
}
#include "jpeg.h"
void CMainFrame::SaveDIB(LPCTSTR fn, BYTE* pData, long size)
{
CString ext = CString(CPath(fn).GetExtension()).MakeLower();
if(ext == _T(".bmp"))
{
if(FILE* f = _tfopen(fn, _T("wb")))
{
BITMAPINFO* bi = (BITMAPINFO*)pData;
BITMAPFILEHEADER bfh;
bfh.bfType = 'MB';
bfh.bfOffBits = sizeof(bfh) + sizeof(bi->bmiHeader);
bfh.bfSize = sizeof(bfh) + size;
bfh.bfReserved1 = bfh.bfReserved2 = 0;
if(bi->bmiHeader.biBitCount <= 8)
{
if(bi->bmiHeader.biClrUsed) bfh.bfOffBits += bi->bmiHeader.biClrUsed * sizeof(bi->bmiColors[0]);
else bfh.bfOffBits += (1 << bi->bmiHeader.biBitCount) * sizeof(bi->bmiColors[0]);
}
fwrite(&bfh, 1, sizeof(bfh), f);
fwrite(pData, 1, size, f);
fclose(f);
}
else
{
AfxMessageBox(_T("Cannot create file"), MB_OK);
}
}
else if(ext == _T(".jpg"))
{
CJpegEncoderFile(fn).Encode(pData);
}
CPath p(fn);
if(CDC* pDC = m_wndStatusBar.m_status.GetDC())
{
CRect r;
m_wndStatusBar.m_status.GetClientRect(r);
p.CompactPath(pDC->m_hDC, r.Width());
m_wndStatusBar.m_status.ReleaseDC(pDC);
}
SendStatusMessage((LPCTSTR)p, 3000);
}
void CMainFrame::SaveImage(LPCTSTR fn)
{
BYTE* pData = NULL;
long size = 0;
if(GetDIB(&pData, size))
{
SaveDIB(fn, pData, size);
delete [] pData;
}
}
void CMainFrame::SaveThumbnails(LPCTSTR fn)
{
if(!pMC || !pMS || m_iPlaybackMode != PM_FILE /*&& m_iPlaybackMode != PM_DVD*/)
return;
REFERENCE_TIME rtPos = GetPos();
REFERENCE_TIME rtDur = GetDur();
if(rtDur <= 0)
{
AfxMessageBox(_T("Cannot create thumbnails for files with no duration"));
return;
}
pMC->Pause();
GetMediaState(); // wait for completion of the pause command
//
CSize video, wh(0, 0), arxy(0, 0);
if(m_pCAP)
{
wh = m_pCAP->GetVideoSize(false);
arxy = m_pCAP->GetVideoSize(true);
}
else
{
pBV->GetVideoSize(&wh.cx, &wh.cy);
long arx = 0, ary = 0;
CComQIPtr<IBasicVideo2> pBV2 = pBV;
if(pBV2 && SUCCEEDED(pBV2->GetPreferredAspectRatio(&arx, &ary)) && arx > 0 && ary > 0)
arxy.SetSize(arx, ary);
}
if(wh.cx <= 0 || wh.cy <= 0)
{
AfxMessageBox(_T("Failed to get video frame size"));
return;
}
// with the overlay mixer IBasicVideo2 won't tell the new AR when changed dynamically
DVD_VideoAttributes VATR;
if(m_iPlaybackMode == PM_DVD && SUCCEEDED(pDVDI->GetCurrentVideoAttributes(&VATR)))
arxy.SetSize(VATR.ulAspectX, VATR.ulAspectY);
video = (arxy.cx <= 0 || arxy.cy <= 0) ? wh : CSize(MulDiv(wh.cy, arxy.cx, arxy.cy), wh.cy);
//
AppSettings& s = AfxGetAppSettings();
int cols = s.ThumbCols, rows = s.ThumbRows;
int margin = 5;
int infoheight = 70;
int width = s.ThumbWidth;
int height = width * video.cy / video.cx * rows / cols + infoheight;
int dibsize = sizeof(BITMAPINFOHEADER) + width*height*4;
CAutoVectorPtr<BYTE> dib;
if(!dib.Allocate(dibsize))
{
AfxMessageBox(_T("Out of memory, go buy some more!"));
return;
}
BITMAPINFOHEADER* bih = (BITMAPINFOHEADER*)(BYTE*)dib;
memset(bih, 0, sizeof(BITMAPINFOHEADER));
bih->biSize = sizeof(BITMAPINFOHEADER);
bih->biWidth = width;
bih->biHeight = height;
bih->biPlanes = 1;
bih->biBitCount = 32;
bih->biCompression = BI_RGB;
bih->biSizeImage = width*height*4;
memsetd(bih + 1, 0xffffff, bih->biSizeImage);
SubPicDesc spd;
spd.w = width;
spd.h = height;
spd.bpp = 32;
spd.pitch = -width*4;
spd.bits = (BYTE*)(bih + 1) + (width*4)*(height-1);
{
BYTE* p = (BYTE*)spd.bits;
for(int y = 0; y < spd.h; y++, p += spd.pitch)
for(int x = 0; x < spd.w; x++)
((DWORD*)p)[x] = 0x010101 * (0xe0 + 0x08*y/spd.h + 0x18*(spd.w-x)/spd.w);
}
CCritSec csSubLock;
RECT bbox;
for(int i = 1, pics = cols*rows; i <= pics; i++)
{
REFERENCE_TIME rt = rtDur * i / (pics+1);
DVD_HMSF_TIMECODE hmsf = RT2HMSF(rt, 25);
SeekTo(rt);
m_VolumeBeforeFrameStepping = m_wndToolBar.Volume;
pBA->put_Volume(-10000);
HRESULT hr = pFS ? pFS->Step(1, NULL) : E_FAIL;
if(FAILED(hr))
{
pBA->put_Volume(m_VolumeBeforeFrameStepping);
AfxMessageBox(_T("Cannot frame step, try a different video renderer."));
return;
}
HANDLE hGraphEvent = NULL;
pME->GetEventHandle((OAEVENT*)&hGraphEvent);
while(hGraphEvent && WaitForSingleObject(hGraphEvent, INFINITE) == WAIT_OBJECT_0)
{
LONG evCode = 0, evParam1, evParam2;
while(SUCCEEDED(pME->GetEvent(&evCode, (LONG_PTR*)&evParam1, (LONG_PTR*)&evParam2, 0)))
{
pME->FreeEventParams(evCode, evParam1, evParam2);
if(EC_STEP_COMPLETE == evCode) hGraphEvent = NULL;
}
}
pBA->put_Volume(m_VolumeBeforeFrameStepping);
int col = (i-1)%cols;
int row = (i-1)/cols;
CSize s((width-margin*2)/cols, (height-margin*2-infoheight)/rows);
CPoint p(margin+col*s.cx, margin+row*s.cy+infoheight);
CRect r(p, s);
r.DeflateRect(margin, margin);
CRenderedTextSubtitle rts(&csSubLock);
rts.CreateDefaultStyle(0);
rts.m_dstScreenSize.SetSize(width, height);
STSStyle* style = new STSStyle();
style->marginRect.SetRectEmpty();
rts.AddStyle(_T("thumbs"), style);
CStringW str;
str.Format(L"{\\an7\\1c&Hffffff&\\4a&Hb0&\\bord1\\shad4\\be1}{\\p1}m %d %d l %d %d %d %d %d %d{\\p}",
r.left, r.top, r.right, r.top, r.right, r.bottom, r.left, r.bottom);
rts.Add(str, true, 0, 1, _T("thumbs"));
str.Format(L"{\\an3\\1c&Hffffff&\\3c&H000000&\\alpha&H80&\\fs16\\b1\\bord2\\shad0\\pos(%d,%d)}%02d:%02d:%02d",
r.right-5, r.bottom-3, hmsf.bHours, hmsf.bMinutes, hmsf.bSeconds);
rts.Add(str, true, 1, 2, _T("thumbs"));
rts.Render(spd, 0, 25, bbox);
BYTE* pData = NULL;
long size = 0;
if(!GetDIB(&pData, size)) return;
BITMAPINFO* bi = (BITMAPINFO*)pData;
if(bi->bmiHeader.biBitCount != 32)
{
delete [] pData;
CString str;
str.Format(_T("Invalid image format, cannot create thumbnails out of %d bpp dibs."), bi->bmiHeader.biBitCount);
AfxMessageBox(str);
return;
}
int sw = bi->bmiHeader.biWidth;
int sh = abs(bi->bmiHeader.biHeight);
int sp = sw*4;
const BYTE* src = pData + sizeof(bi->bmiHeader);
if(bi->bmiHeader.biHeight >= 0) {src += sp*(sh-1); sp = -sp;}
int dw = spd.w;
int dh = spd.h;
int dp = spd.pitch;
BYTE* dst = (BYTE*)spd.bits + spd.pitch*r.top + r.left*4;
for(DWORD h = r.bottom - r.top, y = 0, yd = (sh<<8)/h; h > 0; y += yd, h--)
{
DWORD yf = y&0xff;
DWORD yi = y>>8;
DWORD* s0 = (DWORD*)(src + yi*sp);
DWORD* s1 = (DWORD*)(src + yi*sp + sp);
DWORD* d = (DWORD*)dst;
for(DWORD w = r.right - r.left, x = 0, xd = (sw<<8)/w; w > 0; x += xd, w--)
{
DWORD xf = x&0xff;
DWORD xi = x>>8;
DWORD c0 = s0[xi];
DWORD c1 = s0[xi+1];
DWORD c2 = s1[xi];
DWORD c3 = s1[xi+1];
c0 = ((c0&0xff00ff) + ((((c1&0xff00ff) - (c0&0xff00ff)) * xf) >> 8)) & 0xff00ff
| ((c0&0x00ff00) + ((((c1&0x00ff00) - (c0&0x00ff00)) * xf) >> 8)) & 0x00ff00;
c2 = ((c2&0xff00ff) + ((((c3&0xff00ff) - (c2&0xff00ff)) * xf) >> 8)) & 0xff00ff
| ((c2&0x00ff00) + ((((c3&0x00ff00) - (c2&0x00ff00)) * xf) >> 8)) & 0x00ff00;
c0 = ((c0&0xff00ff) + ((((c2&0xff00ff) - (c0&0xff00ff)) * yf) >> 8)) & 0xff00ff
| ((c0&0x00ff00) + ((((c2&0x00ff00) - (c0&0x00ff00)) * yf) >> 8)) & 0x00ff00;
*d++ = c0;
}
dst += dp;
}
rts.Render(spd, 10000, 25, bbox);
delete [] pData;
}
{
CRenderedTextSubtitle rts(&csSubLock);
rts.CreateDefaultStyle(0);
rts.m_dstScreenSize.SetSize(width, height);
STSStyle* style = new STSStyle();
style->marginRect.SetRect(margin*2, margin*2, margin*2, height-infoheight-margin);
rts.AddStyle(_T("thumbs"), style);
CStringW str;
str.Format(L"{\\an9\\fs%d\\b1\\bord0\\shad0\\1c&Hffffff&}%s", infoheight-10, width >= 550 ? L"Media Player Classic" : L"MPC");
rts.Add(str, true, 0, 1, _T("thumbs"), _T(""), _T(""), CRect(0,0,0,0), -1);
DVD_HMSF_TIMECODE hmsf = RT2HMSF(rtDur, 25);
CPath path(m_wndPlaylistBar.GetCur());
path.StripPath();
CStringW fn = (LPCTSTR)path;
CStringW fs;
WIN32_FIND_DATA wfd;
HANDLE hFind = FindFirstFile(m_wndPlaylistBar.GetCur(), &wfd);
if(hFind != INVALID_HANDLE_VALUE)
{
FindClose(hFind);
__int64 size = (__int64(wfd.nFileSizeHigh)<<32)|wfd.nFileSizeLow;
__int64 shortsize = size;
CStringW measure = _T("B");
if(shortsize > 10240) shortsize /= 1024, measure = L"KB";
if(shortsize > 10240) shortsize /= 1024, measure = L"MB";
if(shortsize > 10240) shortsize /= 1024, measure = L"GB";
fs.Format(L"File Size: %I64d%s (%I64d bytes)\\N", shortsize, measure, size);
}
CStringW ar;
if(arxy.cx > 0 && arxy.cy > 0 && arxy.cx != wh.cx && arxy.cy != wh.cy)
ar.Format(L"(%d:%d)", arxy.cx, arxy.cy);
str.Format(L"{\\an7\\1c&H000000&\\fs16\\b0\\bord0\\shad0}File Name: %s\\N%sResolution: %dx%d %s\\NDuration: %02d:%02d:%02d",
fn, fs, wh.cx, wh.cy, ar, hmsf.bHours, hmsf.bMinutes, hmsf.bSeconds);
rts.Add(str, true, 0, 1, _T("thumbs"));
rts.Render(spd, 0, 25, bbox);
}
SaveDIB(fn, (BYTE*)dib, dibsize);
SeekTo(rtPos);
}
static CString MakeSnapshotFileName(LPCTSTR prefix)
{
CTime t = CTime::GetCurrentTime();
CString fn;
fn.Format(_T("%s%s%s"), prefix, t.Format(_T("%Y%m%d%H%M%S")), AfxGetAppSettings().SnapShotExt);
return fn;
}
void CMainFrame::OnFileSaveImage()
{
AppSettings& s = AfxGetAppSettings();
CPath psrc(s.SnapShotPath);
psrc.Combine(s.SnapShotPath, MakeSnapshotFileName(_T("snapshot")));
CFileDialog fd(FALSE, 0, (LPCTSTR)psrc,
OFN_EXPLORER|OFN_ENABLESIZING|OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_PATHMUSTEXIST,
_T("Bitmaps (*.bmp)|*.bmp|Jpeg (*.jpg)|*.jpg||"), this, 0);
if(s.SnapShotExt == _T(".bmp")) fd.m_pOFN->nFilterIndex = 1;
else if(s.SnapShotExt == _T(".jpg")) fd.m_pOFN->nFilterIndex = 2;
if(fd.DoModal() != IDOK) return;
if(fd.m_pOFN->nFilterIndex == 1) s.SnapShotExt = _T(".bmp");
else if(fd.m_pOFN->nFilterIndex = 2) s.SnapShotExt = _T(".jpg");
CPath pdst(fd.GetPathName());
if(pdst.GetExtension().MakeLower() != s.SnapShotExt) pdst = CPath((LPCTSTR)pdst + s.SnapShotExt);
CString path = (LPCTSTR)pdst;
pdst.RemoveFileSpec();
s.SnapShotPath = (LPCTSTR)pdst;
SaveImage(path);
}
void CMainFrame::OnFileSaveImageAuto()
{
CString fn;
fn.Format(_T("%s\\%s"), AfxGetAppSettings().SnapShotPath, MakeSnapshotFileName(_T("snapshot")));
SaveImage(fn);
}
void CMainFrame::OnUpdateFileSaveImage(CCmdUI* pCmdUI)
{
OAFilterState fs = GetMediaState();
pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly && (fs == State_Paused || fs == State_Running));
}
void CMainFrame::OnFileSaveThumbnails()
{
AppSettings& s = AfxGetAppSettings();
CPath psrc(s.SnapShotPath);
psrc.Combine(s.SnapShotPath, MakeSnapshotFileName(_T("thumbs")));
CSaveThumbnailsDialog fd(
s.ThumbRows, s.ThumbCols, s.ThumbWidth,
0, (LPCTSTR)psrc,
_T("Bitmaps (*.bmp)|*.bmp|Jpeg (*.jpg)|*.jpg||"), this);
if(s.SnapShotExt == _T(".bmp")) fd.m_pOFN->nFilterIndex = 1;
else if(s.SnapShotExt == _T(".jpg")) fd.m_pOFN->nFilterIndex = 2;
if(fd.DoModal() != IDOK) return;
if(fd.m_pOFN->nFilterIndex == 1) s.SnapShotExt = _T(".bmp");
else if(fd.m_pOFN->nFilterIndex = 2) s.SnapShotExt = _T(".jpg");
s.ThumbRows = fd.m_rows;
s.ThumbCols = fd.m_cols;
s.ThumbWidth = fd.m_width;
CPath pdst(fd.GetPathName());
if(pdst.GetExtension().MakeLower() != s.SnapShotExt) pdst = CPath((LPCTSTR)pdst + s.SnapShotExt);
CString path = (LPCTSTR)pdst;
pdst.RemoveFileSpec();
s.SnapShotPath = (LPCTSTR)pdst;
SaveThumbnails(path);
}
void CMainFrame::OnUpdateFileSaveThumbnails(CCmdUI* pCmdUI)
{
OAFilterState fs = GetMediaState();
pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly && (m_iPlaybackMode == PM_FILE /*|| m_iPlaybackMode == PM_DVD*/));
}
void CMainFrame::OnFileConvert()
{
CConvertDlg().DoModal();
}
void CMainFrame::OnUpdateFileConvert(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
}
void CMainFrame::OnFileLoadsubtitle()
{
#ifndef DEBUG
if(!m_pCAP)
{
AfxMessageBox(_T("To load subtitles you have change the video renderer type and reopen the file.\n")
_T("- DirectShow: VMR7/VMR9 renderless or Haali's\n")
_T("- RealMedia: Special renderer for RealMedia, or open it through DirectShow\n")
_T("- Quicktime: DX7 or DX9 renderer for QuickTime\n")
_T("- ShockWave: n/a\n")
, MB_OK);
return;
}
#endif
static TCHAR BASED_CODE szFilter[] =
_T(".srt .sub .ssa .ass .smi .psb .txt .idx .usf .xss .ssf|")
_T("*.srt;*.sub;*.ssa;*.ass;*smi;*.psb;*.txt;*.idx;*.usf;*.xss;*.ssf|")
_T("All files (*.*)|")
_T("*.*||");
CFileDialog fd(TRUE, NULL, NULL,
OFN_EXPLORER | OFN_ENABLESIZING | OFN_HIDEREADONLY,
szFilter, this, 0);
if(fd.DoModal() != IDOK) return;
if(LoadSubtitle(fd.GetPathName()))
SetSubtitle(m_pSubStreams.GetTail());
}
void CMainFrame::OnUpdateFileLoadsubtitle(CCmdUI *pCmdUI)
{
#ifdef DEBUG
pCmdUI->Enable();
#else
pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && /*m_pCAP &&*/ !m_fAudioOnly);
#endif
}
void CMainFrame::OnFileSavesubtitle()
{
int i = m_iSubtitleSel;
POSITION pos = m_pSubStreams.GetHeadPosition();
while(pos && i >= 0)
{
CComPtr<ISubStream> pSubStream = m_pSubStreams.GetNext(pos);
if(i < pSubStream->GetStreamCount())
{
CLSID clsid;
if(FAILED(pSubStream->GetClassID(&clsid)))
continue;
if(clsid == __uuidof(CVobSubFile))
{
CVobSubFile* pVSF = (CVobSubFile*)(ISubStream*)pSubStream;
CFileDialog fd(FALSE, NULL, NULL,
OFN_EXPLORER|OFN_ENABLESIZING|OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_PATHMUSTEXIST,
_T("VobSub (*.idx, *.sub)|*.idx;*.sub||"), this, 0);
if(fd.DoModal() == IDOK)
{
CAutoLock cAutoLock(&m_csSubLock);
pVSF->Save(fd.GetPathName());
}
return;
}
else if(clsid == __uuidof(CRenderedTextSubtitle))
{
CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)pSubStream;
CString filter;
filter += _T("Subripper (*.srt)|*.srt|");
filter += _T("Microdvd (*.sub)|*.sub|");
filter += _T("Sami (*.smi)|*.smi|");
filter += _T("Psb (*.psb)|*.psb|");
filter += _T("Sub Station Alpha (*.ssa)|*.ssa|");
filter += _T("Advanced Sub Station Alpha (*.ass)|*.ass|");
filter += _T("|");
CSaveTextFileDialog fd(pRTS->m_encoding, NULL, NULL, filter, this);
if(fd.DoModal() == IDOK)
{
CAutoLock cAutoLock(&m_csSubLock);
pRTS->SaveAs(fd.GetPathName(), (exttype)(fd.m_ofn.nFilterIndex-1), m_pCAP->GetFPS(), fd.GetEncoding());
}
return;
}
}
i -= pSubStream->GetStreamCount();
}
}
void CMainFrame::OnUpdateFileSavesubtitle(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_iSubtitleSel >= 0);
}
///////////////
#include "SubtitleDlDlg.h"
#include "ISDb.h"
void CMainFrame::OnFileISDBSearch()
{
CStringA url = "http://" + AfxGetAppSettings().ISDb + "/index.php?";
CStringA args = makeargs(m_wndPlaylistBar.m_pl);
ShellExecute(m_hWnd, _T("open"), CString(url+args), NULL, NULL, SW_SHOWDEFAULT);
}
void CMainFrame::OnUpdateFileISDBSearch(CCmdUI *pCmdUI)
{
pCmdUI->Enable(TRUE);
}
void CMainFrame::OnFileISDBUpload()
{
CStringA url = "http://" + AfxGetAppSettings().ISDb + "/ul.php?";
CStringA args = makeargs(m_wndPlaylistBar.m_pl);
ShellExecute(m_hWnd, _T("open"), CString(url+args), NULL, NULL, SW_SHOWDEFAULT);
}
void CMainFrame::OnUpdateFileISDBUpload(CCmdUI *pCmdUI)
{
pCmdUI->Enable(m_wndPlaylistBar.GetCount() > 0);
}
void CMainFrame::OnFileISDBDownload()
{
filehash fh;
if(!hash(m_wndPlaylistBar.GetCur(), fh))
{
MessageBeep(-1);
return;
}
// TODO: put this on a worker thread
CStringA url = "http://" + AfxGetAppSettings().ISDb + "/index.php?";
CStringA args;
args.Format("player=mpc&name[0]=%s&size[0]=%016I64x&hash[0]=%016I64x",
UrlEncode(CStringA(fh.name)), fh.size, fh.hash);
try
{
CInternetSession is;
CStringA str;
if(!OpenUrl(is, CString(url+args), str))
{
MessageBeep(-1);
return;
}
CStringA ticket;
CList<isdb_movie> movies;
isdb_movie m;
isdb_subtitle s;
CAtlList<CStringA> sl;
Explode(str, sl, '\n');
POSITION pos = sl.GetHeadPosition();
while(pos)
{
str = sl.GetNext(pos);
CStringA param = str.Left(max(0, str.Find('=')));
CStringA value = str.Mid(str.Find('=')+1);
if(param == "ticket") ticket = value;
else if(param == "movie") {m.reset(); Explode(value, m.titles, '|');}
else if(param == "subtitle") {s.reset(); s.id = atoi(value);}
else if(param == "name") s.name = value;
else if(param == "discs") s.discs = atoi(value);
else if(param == "disc_no") s.disc_no = atoi(value);
else if(param == "format") s.format = value;
else if(param == "iso639_2") s.iso639_2 = value;
else if(param == "language") s.language = value;
else if(param == "nick") s.nick = value;
else if(param == "email") s.email = value;
else if(param == "" && value == "endsubtitle") {m.subs.AddTail(s);}
else if(param == "" && value == "endmovie") {movies.AddTail(m);}
else if(param == "" && value == "end") break;
}
CSubtitleDlDlg dlg(movies, this);
if(IDOK == dlg.DoModal())
{
if(dlg.m_fReplaceSubs)
m_pSubStreams.RemoveAll();
CComPtr<ISubStream> pSubStreamToSet;
POSITION pos = dlg.m_selsubs.GetHeadPosition();
while(pos)
{
isdb_subtitle& s = dlg.m_selsubs.GetNext(pos);
CStringA url = "http://" + AfxGetAppSettings().ISDb + "/dl.php?";
CStringA args;
args.Format("id=%d&ticket=%s", s.id, UrlEncode(ticket));
if(OpenUrl(is, CString(url+args), str))
{
CComPtr<ISubStream> pSubStream;
if(!pSubStream)
{
CAutoPtr<ssf::CRenderer> p(new ssf::CRenderer(&m_csSubLock));
if(p->Open(ssf::MemoryInputStream((BYTE*)(LPCSTR)str, str.GetLength(), false, false), CString(s.name)) && p->GetStreamCount() > 0)
{
pSubStream = p.Detach();
}
}
if(!pSubStream)
{
CAutoPtr<CRenderedTextSubtitle> p(new CRenderedTextSubtitle(&m_csSubLock));
if(p->Open((BYTE*)(LPCSTR)str, str.GetLength(), DEFAULT_CHARSET, CString(s.name)) && p->GetStreamCount() > 0)
{
pSubStream = p.Detach();
}
}
if(pSubStream)
{
m_pSubStreams.AddTail(pSubStream);
if(!pSubStreamToSet) pSubStreamToSet = pSubStream;
}
}
}
if(pSubStreamToSet)
SetSubtitle(pSubStreamToSet);
}
}
catch(CInternetException* ie)
{
ie->Delete();
return;
}
}
void CMainFrame::OnUpdateFileISDBDownload(CCmdUI *pCmdUI)
{
pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && m_pCAP && !m_fAudioOnly);
}
void CMainFrame::OnFileProperties()
{
CPPageFileInfoSheet m_fileinfo(m_wndPlaylistBar.GetCur(), this);
m_fileinfo.DoModal();
}
void CMainFrame::OnUpdateFileProperties(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && m_iPlaybackMode == PM_FILE);
}
void CMainFrame::OnFileCloseMedia()
{
CloseMedia();
}
void CMainFrame::OnFileClosePlaylist()
{
SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
RestoreDefaultWindowRect();
}
void CMainFrame::OnUpdateFileClose(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED || m_iMediaLoadState == MLS_LOADING);
}
// view
void CMainFrame::OnViewCaptionmenu()
{
bool fHideCaptionMenu = AfxGetAppSettings().fHideCaptionMenu;
AfxGetAppSettings().fHideCaptionMenu = !fHideCaptionMenu;
if(m_fFullScreen) return;
DWORD dwRemove = 0, dwAdd = 0;
HMENU hMenu;
if(!fHideCaptionMenu)
{
dwRemove = WS_CAPTION;
hMenu = NULL;
}
else
{
dwAdd = WS_CAPTION;
hMenu = m_hMenuDefault;
}
ModifyStyle(dwRemove, dwAdd, SWP_NOZORDER);
::SetMenu(m_hWnd, hMenu);
SetWindowPos(NULL, 0, 0, 0, 0, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER);
MoveVideoWindow();
}
void CMainFrame::OnUpdateViewCaptionmenu(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(!AfxGetAppSettings().fHideCaptionMenu);
}
void CMainFrame::OnViewControlBar(UINT nID)
{
nID -= ID_VIEW_SEEKER;
ShowControls(AfxGetAppSettings().nCS ^ (1<<nID));
}
void CMainFrame::OnUpdateViewControlBar(CCmdUI* pCmdUI)
{
UINT nID = pCmdUI->m_nID - ID_VIEW_SEEKER;
pCmdUI->SetCheck(!!(AfxGetAppSettings().nCS & (1<<nID)));
}
void CMainFrame::OnViewSubresync()
{
ShowControlBar(&m_wndSubresyncBar, !m_wndSubresyncBar.IsWindowVisible(), TRUE);
}
void CMainFrame::OnUpdateViewSubresync(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(m_wndSubresyncBar.IsWindowVisible());
pCmdUI->Enable(m_pCAP && m_iSubtitleSel >= 0);
}
void CMainFrame::OnViewPlaylist()
{
ShowControlBar(&m_wndPlaylistBar, !m_wndPlaylistBar.IsWindowVisible(), TRUE);
}
void CMainFrame::OnUpdateViewPlaylist(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(m_wndPlaylistBar.IsWindowVisible());
pCmdUI->Enable(m_iMediaLoadState == MLS_CLOSED && m_iMediaLoadState != MLS_LOADED
|| m_iMediaLoadState == MLS_LOADED /*&& (m_iPlaybackMode == PM_FILE || m_iPlaybackMode == PM_CAPTURE)*/);
}
void CMainFrame::OnViewCapture()
{
ShowControlBar(&m_wndCaptureBar, !m_wndCaptureBar.IsWindowVisible(), TRUE);
}
void CMainFrame::OnUpdateViewCapture(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(m_wndCaptureBar.IsWindowVisible());
pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && m_iPlaybackMode == PM_CAPTURE);
}
void CMainFrame::OnViewShaderEditor()
{
ShowControlBar(&m_wndShaderEditorBar, !m_wndShaderEditorBar.IsWindowVisible(), TRUE);
}
void CMainFrame::OnUpdateViewShaderEditor(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(m_wndShaderEditorBar.IsWindowVisible());
pCmdUI->Enable(TRUE);
}
void CMainFrame::OnViewMinimal()
{
if(!AfxGetAppSettings().fHideCaptionMenu)
SendMessage(WM_COMMAND, ID_VIEW_CAPTIONMENU);
ShowControls(0);
}
void CMainFrame::OnUpdateViewMinimal(CCmdUI* pCmdUI)
{
}
void CMainFrame::OnViewCompact()
{
if(AfxGetAppSettings().fHideCaptionMenu)
SendMessage(WM_COMMAND, ID_VIEW_CAPTIONMENU);
ShowControls(CS_TOOLBAR);
}
void CMainFrame::OnUpdateViewCompact(CCmdUI* pCmdUI)
{
}
void CMainFrame::OnViewNormal()
{
if(AfxGetAppSettings().fHideCaptionMenu)
SendMessage(WM_COMMAND, ID_VIEW_CAPTIONMENU);
ShowControls(CS_SEEKBAR|CS_TOOLBAR|CS_STATUSBAR|CS_INFOBAR);
}
void CMainFrame::OnUpdateViewNormal(CCmdUI* pCmdUI)
{
}
void CMainFrame::OnViewFullscreen()
{
ToggleFullscreen(true, true);
}
void CMainFrame::OnViewFullscreenSecondary()
{
ToggleFullscreen(true, false);
}
void CMainFrame::OnUpdateViewFullscreen(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly || m_fFullScreen);
pCmdUI->SetCheck(m_fFullScreen);
}
void CMainFrame::OnViewZoom(UINT nID)
{
ZoomVideoWindow(nID == ID_VIEW_ZOOM_50 ? 0.5 : nID == ID_VIEW_ZOOM_200 ? 2.0 : 1.0);
}
void CMainFrame::OnUpdateViewZoom(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly);
}
void CMainFrame::OnViewZoomAutoFit()
{
ZoomVideoWindow(GetZoomAutoFitScale());
}
void CMainFrame::OnViewDefaultVideoFrame(UINT nID)
{
AfxGetAppSettings().iDefaultVideoSize = nID - ID_VIEW_VF_HALF;
m_ZoomX = m_ZoomY = 1;
m_PosX = m_PosY = 0.5;
MoveVideoWindow();
}
void CMainFrame::OnUpdateViewDefaultVideoFrame(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly);
pCmdUI->SetRadio(AfxGetAppSettings().iDefaultVideoSize == (pCmdUI->m_nID - ID_VIEW_VF_HALF));
}
void CMainFrame::OnViewKeepaspectratio()
{
AfxGetAppSettings().fKeepAspectRatio = !AfxGetAppSettings().fKeepAspectRatio;
MoveVideoWindow();
}
void CMainFrame::OnUpdateViewKeepaspectratio(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly);
pCmdUI->SetCheck(AfxGetAppSettings().fKeepAspectRatio);
}
void CMainFrame::OnViewCompMonDeskARDiff()
{
AfxGetAppSettings().fCompMonDeskARDiff = !AfxGetAppSettings().fCompMonDeskARDiff;
MoveVideoWindow();
}
void CMainFrame::OnUpdateViewCompMonDeskARDiff(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly);
pCmdUI->SetCheck(AfxGetAppSettings().fCompMonDeskARDiff);
}
void CMainFrame::OnViewPanNScan(UINT nID)
{
if(m_iMediaLoadState != MLS_LOADED) return;
int x = 0, y = 0;
int dx = 0, dy = 0;
switch(nID)
{
case ID_VIEW_RESET: m_ZoomX = m_ZoomY = 1.0; m_PosX = m_PosY = 0.5; m_AngleX = m_AngleY = m_AngleZ = 0; break;
case ID_VIEW_INCSIZE: x = y = 1; break;
case ID_VIEW_DECSIZE: x = y = -1; break;
case ID_VIEW_INCWIDTH: x = 1; break;
case ID_VIEW_DECWIDTH: x = -1; break;
case ID_VIEW_INCHEIGHT: y = 1; break;
case ID_VIEW_DECHEIGHT: y = -1; break;
case ID_PANSCAN_CENTER: m_PosX = m_PosY = 0.5; break;
case ID_PANSCAN_MOVELEFT: dx = -1; break;
case ID_PANSCAN_MOVERIGHT: dx = 1; break;
case ID_PANSCAN_MOVEUP: dy = -1; break;
case ID_PANSCAN_MOVEDOWN: dy = 1; break;
case ID_PANSCAN_MOVEUPLEFT: dx = dy = -1; break;
case ID_PANSCAN_MOVEUPRIGHT: dx = 1; dy = -1; break;
case ID_PANSCAN_MOVEDOWNLEFT: dx = -1; dy = 1; break;
case ID_PANSCAN_MOVEDOWNRIGHT: dx = dy = 1; break;
default: break;
}
if(x > 0 && m_ZoomX < 3) m_ZoomX *= 1.02;
if(x < 0 && m_ZoomX > 0.2) m_ZoomX /= 1.02;
if(y > 0 && m_ZoomY < 3) m_ZoomY *= 1.02;
if(y < 0 && m_ZoomY > 0.2) m_ZoomY /= 1.02;
if(dx < 0 && m_PosX > 0) m_PosX = max(m_PosX - 0.005*m_ZoomX, 0);
if(dx > 0 && m_PosX < 1) m_PosX = min(m_PosX + 0.005*m_ZoomX, 1);
if(dy < 0 && m_PosY > 0) m_PosY = max(m_PosY - 0.005*m_ZoomY, 0);
if(dy > 0 && m_PosY < 1) m_PosY = min(m_PosY + 0.005*m_ZoomY, 1);
MoveVideoWindow(true);
}
void CMainFrame::OnUpdateViewPanNScan(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly);
}
void CMainFrame::OnViewPanNScanPresets(UINT nID)
{
if(m_iMediaLoadState != MLS_LOADED) return;
AppSettings& s = AfxGetAppSettings();
nID -= ID_PANNSCAN_PRESETS_START;
if(nID == s.m_pnspresets.GetCount())
{
CPnSPresetsDlg dlg;
dlg.m_pnspresets.Copy(s.m_pnspresets);
if(dlg.DoModal() == IDOK)
{
s.m_pnspresets.Copy(dlg.m_pnspresets);
s.UpdateData(true);
}
return;
}
m_PosX = 0.5;
m_PosY = 0.5;
m_ZoomX = 1.0;
m_ZoomY = 1.0;
CString str = s.m_pnspresets[nID];
int i = 0, j = 0;
for(CString token = str.Tokenize(_T(","), i); !token.IsEmpty(); token = str.Tokenize(_T(","), i), j++)
{
float f = 0;
if(_stscanf(token, _T("%f"), &f) != 1) continue;
switch(j)
{
case 0: break;
case 1: m_PosX = f; break;
case 2: m_PosY = f; break;
case 3: m_ZoomX = f; break;
case 4: m_ZoomY = f; break;
default: break;
}
}
if(j != 5) return;
m_PosX = min(max(m_PosX, 0), 1);
m_PosY = min(max(m_PosY, 0), 1);
m_ZoomX = min(max(m_ZoomX, 0.2), 3);
m_ZoomY = min(max(m_ZoomY, 0.2), 3);
MoveVideoWindow(true);
}
void CMainFrame::OnUpdateViewPanNScanPresets(CCmdUI* pCmdUI)
{
int nID = pCmdUI->m_nID - ID_PANNSCAN_PRESETS_START;
AppSettings& s = AfxGetAppSettings();
pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly && nID >= 0 && nID <= s.m_pnspresets.GetCount());
}
void CMainFrame::OnViewRotate(UINT nID)
{
if(!m_pCAP) return;
switch(nID)
{
case ID_PANSCAN_ROTATEXP: m_AngleX += 2; break;
case ID_PANSCAN_ROTATEXM: m_A