/*
* $Id$
*
* (C) 2003-2006 Gabest
* (C) 2006-2011 see AUTHORS
*
* This file is part of mplayerc.
*
* Mplayerc 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 3 of the License, or
* (at your option) any later version.
*
* Mplayerc 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 this program. If not, see .
*
*/
#include "stdafx.h"
#include "mplayerc.h"
#include "MainFrm.h"
#include
#include
#include
#include
#include
#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 "FullscreenWnd.h"
#include "TunerScanDlg.h"
#include "OpenDirHelper.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#include // Casimir666 : incompatible with D3D.h
#include "../../DSUtil/DSUtil.h"
#include "FGManager.h"
#include "FGManagerBDA.h"
#include "TextPassThruFilter.h"
#include "../../filters/filters.h"
#include "../../filters/PinInfoWnd.h"
#include "AllocatorCommon7.h"
#include "AllocatorCommon.h"
#include "SyncAllocatorPresenter.h"
#include "../../Subtitles/SSF.h"
#include "ComPropertySheet.h"
#include "LcdSupport.h"
#include "SettingsDefines.h"
#include "IPinHook.h"
#define DEFCLIENTW 292
#define DEFCLIENTH 200
static UINT s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
static UINT WM_NOTIFYICON = RegisterWindowMessage(TEXT("MYWM_NOTIFYICON"));
static UINT s_uTBBC = RegisterWindowMessage(TEXT("TaskbarButtonCreated"));
#include "../../filters/transform/VSFilter/IDirectVobSub.h"
#include "Monitors.h"
#include "MultiMonitor.h"
#include "CGdiPlusBitmap.h"
DWORD last_run = 0;
UINT flast_nID = 0;
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); \
} \
using namespace DSObjects;
/////////////////////////////////////////////////////////////////////////////
// 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_REGISTERED_MESSAGE(s_uTBBC, OnTaskBarThumbnailsCreate)
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_INPUT()
ON_MESSAGE(WM_HOTKEY, OnHotKey)
ON_WM_TIMER()
ON_MESSAGE(WM_GRAPHNOTIFY, OnGraphNotify)
ON_MESSAGE(WM_RESET_DEVICE, OnResetDevice)
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_COMMAND(ID_FILE_REOPEN, OnFileReopen)
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_UPDATE_COMMAND_UI(ID_FILE_CLOSEPLAYLIST, OnUpdateFileClose)
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_EDITLISTEDITOR, OnViewEditListEditor)
ON_COMMAND(ID_EDL_IN, OnEDLIn)
ON_UPDATE_COMMAND_UI(ID_EDL_IN, OnUpdateEDLIn)
ON_COMMAND(ID_EDL_OUT, OnEDLOut)
ON_UPDATE_COMMAND_UI(ID_EDL_OUT, OnUpdateEDLOut)
ON_COMMAND(ID_EDL_NEWCLIP, OnEDLNewClip)
ON_UPDATE_COMMAND_UI(ID_EDL_NEWCLIP, OnUpdateEDLNewClip)
ON_COMMAND(ID_EDL_SAVE, OnEDLSave)
ON_UPDATE_COMMAND_UI(ID_EDL_SAVE, OnUpdateEDLSave)
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_ZOOM2, OnViewDefaultVideoFrame)
ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_VF_HALF, ID_VIEW_VF_ZOOM2, OnUpdateViewDefaultVideoFrame)
ON_COMMAND(ID_VIEW_VF_SWITCHZOOM, OnViewSwitchVideoFrame)
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)
// Casimir666
ON_UPDATE_COMMAND_UI(ID_VIEW_TEARING_TEST, OnUpdateViewTearingTest)
ON_COMMAND(ID_VIEW_TEARING_TEST, OnViewTearingTest)
ON_UPDATE_COMMAND_UI(ID_VIEW_DISPLAYSTATS, OnUpdateViewDisplayStats)
ON_COMMAND(ID_VIEW_RESETSTATS, OnViewResetStats)
ON_COMMAND(ID_VIEW_DISPLAYSTATS, OnViewDisplayStatsSC)
ON_UPDATE_COMMAND_UI(ID_VIEW_FULLSCREENGUISUPPORT, OnUpdateViewFullscreenGUISupport)
ON_UPDATE_COMMAND_UI(ID_VIEW_HIGHCOLORRESOLUTION, OnUpdateViewHighColorResolution)
ON_UPDATE_COMMAND_UI(ID_VIEW_FORCEINPUTHIGHCOLORRESOLUTION, OnUpdateViewForceInputHighColorResolution)
ON_UPDATE_COMMAND_UI(ID_VIEW_FULLFLOATINGPOINTPROCESSING, OnUpdateViewFullFloatingPointProcessing)
ON_UPDATE_COMMAND_UI(ID_VIEW_HALFFLOATINGPOINTPROCESSING, OnUpdateViewHalfFloatingPointProcessing)
ON_UPDATE_COMMAND_UI(ID_VIEW_ENABLEFRAMETIMECORRECTION, OnUpdateViewEnableFrameTimeCorrection)
ON_UPDATE_COMMAND_UI(ID_VIEW_VSYNC, OnUpdateViewVSync)
ON_UPDATE_COMMAND_UI(ID_VIEW_VSYNCOFFSET, OnUpdateViewVSyncOffset)
ON_UPDATE_COMMAND_UI(ID_VIEW_VSYNCACCURATE, OnUpdateViewVSyncAccurate)
ON_UPDATE_COMMAND_UI(ID_VIEW_SYNCHRONIZEVIDEO, OnUpdateViewSynchronizeVideo)
ON_UPDATE_COMMAND_UI(ID_VIEW_SYNCHRONIZEDISPLAY, OnUpdateViewSynchronizeDisplay)
ON_UPDATE_COMMAND_UI(ID_VIEW_SYNCHRONIZENEAREST, OnUpdateViewSynchronizeNearest)
ON_UPDATE_COMMAND_UI(ID_VIEW_COLORMANAGEMENT_ENABLE, OnUpdateViewColorManagementEnable)
ON_UPDATE_COMMAND_UI(ID_VIEW_COLORMANAGEMENT_INPUT_AUTO, OnUpdateViewColorManagementInput)
ON_UPDATE_COMMAND_UI(ID_VIEW_COLORMANAGEMENT_INPUT_HDTV, OnUpdateViewColorManagementInput)
ON_UPDATE_COMMAND_UI(ID_VIEW_COLORMANAGEMENT_INPUT_SDTV_NTSC, OnUpdateViewColorManagementInput)
ON_UPDATE_COMMAND_UI(ID_VIEW_COLORMANAGEMENT_INPUT_SDTV_PAL, OnUpdateViewColorManagementInput)
ON_UPDATE_COMMAND_UI(ID_VIEW_COLORMANAGEMENT_AMBIENTLIGHT_BRIGHT, OnUpdateViewColorManagementAmbientLight)
ON_UPDATE_COMMAND_UI(ID_VIEW_COLORMANAGEMENT_AMBIENTLIGHT_DIM, OnUpdateViewColorManagementAmbientLight)
ON_UPDATE_COMMAND_UI(ID_VIEW_COLORMANAGEMENT_AMBIENTLIGHT_DARK, OnUpdateViewColorManagementAmbientLight)
ON_UPDATE_COMMAND_UI(ID_VIEW_COLORMANAGEMENT_INTENT_PERCEPTUAL, OnUpdateViewColorManagementIntent)
ON_UPDATE_COMMAND_UI(ID_VIEW_COLORMANAGEMENT_INTENT_RELATIVECOLORIMETRIC, OnUpdateViewColorManagementIntent)
ON_UPDATE_COMMAND_UI(ID_VIEW_COLORMANAGEMENT_INTENT_SATURATION, OnUpdateViewColorManagementIntent)
ON_UPDATE_COMMAND_UI(ID_VIEW_COLORMANAGEMENT_INTENT_ABSOLUTECOLORIMETRIC, OnUpdateViewColorManagementIntent)
ON_UPDATE_COMMAND_UI(ID_VIEW_EVROUTPUTRANGE_0_255, OnUpdateViewEVROutputRange)
ON_UPDATE_COMMAND_UI(ID_VIEW_EVROUTPUTRANGE_16_235, OnUpdateViewEVROutputRange)
ON_UPDATE_COMMAND_UI(ID_VIEW_FLUSHGPU_BEFOREVSYNC, OnUpdateViewFlushGPU)
ON_UPDATE_COMMAND_UI(ID_VIEW_FLUSHGPU_AFTERPRESENT, OnUpdateViewFlushGPU)
ON_UPDATE_COMMAND_UI(ID_VIEW_FLUSHGPU_WAIT, OnUpdateViewFlushGPU)
ON_UPDATE_COMMAND_UI(ID_VIEW_D3DFULLSCREEN, OnUpdateViewD3DFullscreen)
ON_UPDATE_COMMAND_UI(ID_VIEW_DISABLEDESKTOPCOMPOSITION, OnUpdateViewDisableDesktopComposition)
ON_UPDATE_COMMAND_UI(ID_VIEW_ALTERNATIVEVSYNC, OnUpdateViewAlternativeVSync)
ON_UPDATE_COMMAND_UI(ID_VIEW_VSYNCOFFSET_INCREASE, OnUpdateViewVSyncOffsetIncrease)
ON_UPDATE_COMMAND_UI(ID_VIEW_VSYNCOFFSET_DECREASE, OnUpdateViewVSyncOffsetDecrease)
ON_COMMAND(ID_VIEW_FULLSCREENGUISUPPORT, OnViewFullscreenGUISupport)
ON_COMMAND(ID_VIEW_HIGHCOLORRESOLUTION, OnViewHighColorResolution)
ON_COMMAND(ID_VIEW_FORCEINPUTHIGHCOLORRESOLUTION, OnViewForceInputHighColorResolution)
ON_COMMAND(ID_VIEW_FULLFLOATINGPOINTPROCESSING, OnViewFullFloatingPointProcessing)
ON_COMMAND(ID_VIEW_HALFFLOATINGPOINTPROCESSING, OnViewHalfFloatingPointProcessing)
ON_COMMAND(ID_VIEW_ENABLEFRAMETIMECORRECTION, OnViewEnableFrameTimeCorrection)
ON_COMMAND(ID_VIEW_VSYNC, OnViewVSync)
ON_COMMAND(ID_VIEW_VSYNCACCURATE, OnViewVSyncAccurate)
ON_COMMAND(ID_VIEW_SYNCHRONIZEVIDEO, OnViewSynchronizeVideo)
ON_COMMAND(ID_VIEW_SYNCHRONIZEDISPLAY, OnViewSynchronizeDisplay)
ON_COMMAND(ID_VIEW_SYNCHRONIZENEAREST, OnViewSynchronizeNearest)
ON_COMMAND(ID_VIEW_COLORMANAGEMENT_ENABLE, OnViewColorManagementEnable)
ON_COMMAND(ID_VIEW_COLORMANAGEMENT_INPUT_AUTO, OnViewColorManagementInputAuto)
ON_COMMAND(ID_VIEW_COLORMANAGEMENT_INPUT_HDTV, OnViewColorManagementInputHDTV)
ON_COMMAND(ID_VIEW_COLORMANAGEMENT_INPUT_SDTV_NTSC, OnViewColorManagementInputSDTV_NTSC)
ON_COMMAND(ID_VIEW_COLORMANAGEMENT_INPUT_SDTV_PAL, OnViewColorManagementInputSDTV_PAL)
ON_COMMAND(ID_VIEW_COLORMANAGEMENT_AMBIENTLIGHT_BRIGHT, OnViewColorManagementAmbientLightBright)
ON_COMMAND(ID_VIEW_COLORMANAGEMENT_AMBIENTLIGHT_DIM, OnViewColorManagementAmbientLightDim)
ON_COMMAND(ID_VIEW_COLORMANAGEMENT_AMBIENTLIGHT_DARK, OnViewColorManagementAmbientLightDark)
ON_COMMAND(ID_VIEW_COLORMANAGEMENT_INTENT_PERCEPTUAL, OnViewColorManagementIntentPerceptual)
ON_COMMAND(ID_VIEW_COLORMANAGEMENT_INTENT_RELATIVECOLORIMETRIC, OnViewColorManagementIntentRelativeColorimetric)
ON_COMMAND(ID_VIEW_COLORMANAGEMENT_INTENT_SATURATION, OnViewColorManagementIntentSaturation)
ON_COMMAND(ID_VIEW_COLORMANAGEMENT_INTENT_ABSOLUTECOLORIMETRIC, OnViewColorManagementIntentAbsoluteColorimetric)
ON_COMMAND(ID_VIEW_EVROUTPUTRANGE_0_255, OnViewEVROutputRange_0_255)
ON_COMMAND(ID_VIEW_EVROUTPUTRANGE_16_235, OnViewEVROutputRange_16_235)
ON_COMMAND(ID_VIEW_FLUSHGPU_BEFOREVSYNC, OnViewFlushGPUBeforeVSync)
ON_COMMAND(ID_VIEW_FLUSHGPU_AFTERPRESENT, OnViewFlushGPUAfterVSync)
ON_COMMAND(ID_VIEW_FLUSHGPU_WAIT, OnViewFlushGPUWait)
ON_COMMAND(ID_VIEW_D3DFULLSCREEN, OnViewD3DFullScreen)
ON_COMMAND(ID_VIEW_DISABLEDESKTOPCOMPOSITION, OnViewDisableDesktopComposition)
ON_COMMAND(ID_VIEW_ALTERNATIVEVSYNC, OnViewAlternativeVSync)
ON_COMMAND(ID_VIEW_RESET_DEFAULT, OnViewResetDefault)
ON_COMMAND(ID_VIEW_RESET_OPTIMAL, OnViewResetOptimal)
ON_COMMAND(ID_VIEW_VSYNCOFFSET_INCREASE, OnViewVSyncOffsetIncrease)
ON_COMMAND(ID_VIEW_VSYNCOFFSET_DECREASE, OnViewVSyncOffsetDecrease)
ON_UPDATE_COMMAND_UI(ID_SHADER_TOGGLE, OnUpdateShaderToggle)
ON_COMMAND(ID_SHADER_TOGGLE, OnShaderToggle)
ON_UPDATE_COMMAND_UI(ID_SHADER_TOGGLESCREENSPACE, OnUpdateShaderToggleScreenSpace)
ON_COMMAND(ID_SHADER_TOGGLESCREENSPACE, OnShaderToggleScreenSpace)
ON_UPDATE_COMMAND_UI(ID_VIEW_REMAINING_TIME, OnUpdateViewRemainingTime)
ON_COMMAND(ID_VIEW_REMAINING_TIME, OnViewRemainingTime)
ON_COMMAND(ID_D3DFULLSCREEN_TOGGLE, OnD3DFullscreenToggle)
ON_COMMAND_RANGE(ID_GOTO_PREV_SUB, ID_GOTO_NEXT_SUB, OnGotoSubtitle)
ON_COMMAND_RANGE(ID_SHIFT_SUB_DOWN, ID_SHIFT_SUB_UP, OnShiftSubtitle)
ON_COMMAND_RANGE(ID_SUB_DELAY_DOWN, ID_SUB_DELAY_UP, OnSubtitleDelay)
ON_COMMAND_RANGE(ID_LANGUAGE_ENGLISH, ID_LANGUAGE_LAST, OnLanguage)
ON_UPDATE_COMMAND_UI_RANGE(ID_LANGUAGE_ENGLISH, ID_LANGUAGE_LAST, OnUpdateLanguage)
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_AFTERPLAYBACK_EXIT, ID_AFTERPLAYBACK_NEXT, OnAfterplayback)
ON_UPDATE_COMMAND_UI_RANGE(ID_AFTERPLAYBACK_EXIT, ID_AFTERPLAYBACK_NEXT, 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_NAVIGATE_TUNERSCAN, OnTunerScan)
ON_UPDATE_COMMAND_UI(ID_NAVIGATE_TUNERSCAN, OnUpdateTunerScan)
ON_COMMAND(ID_FAVORITES_ADD, OnFavoritesAdd)
ON_UPDATE_COMMAND_UI(ID_FAVORITES_ADD, OnUpdateFavoritesAdd)
ON_COMMAND(ID_FAVORITES_QUICKADDFAVORITE, OnFavoritesQuickAddFavorite)
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_RECENT_FILES_CLEAR, OnRecentFileClear)
ON_UPDATE_COMMAND_UI(ID_RECENT_FILES_CLEAR, OnUpdateRecentFileClear)
ON_COMMAND_RANGE(ID_RECENT_FILE_START, ID_RECENT_FILE_END, OnRecentFile)
ON_UPDATE_COMMAND_UI_RANGE(ID_RECENT_FILE_START, ID_RECENT_FILE_END, OnUpdateRecentFile)
ON_COMMAND(ID_HELP_HOMEPAGE, OnHelpHomepage)
ON_COMMAND(ID_HELP_DOCUMENTATION, OnHelpDocumentation)
ON_COMMAND(ID_HELP_TOOLBARIMAGES, OnHelpToolbarImages)
//ON_COMMAND(ID_HELP_DONATE, OnHelpDonate)
// Open Dir incl. SubDir
ON_COMMAND(ID_FILE_OPENDIRECTORY, OnFileOpendirectory)
ON_UPDATE_COMMAND_UI(ID_FILE_OPENDIRECTORY, OnUpdateFileOpen)
ON_WM_POWERBROADCAST()
// Navigation pannel
ON_COMMAND(ID_VIEW_NAVIGATION, OnViewNavigation)
ON_UPDATE_COMMAND_UI(ID_VIEW_NAVIGATION, OnUpdateViewNavigation)
END_MESSAGE_MAP()
#ifdef _DEBUG
const TCHAR *GetEventString(LONG evCode)
{
#define UNPACK_VALUE(VALUE) case VALUE: return _T( #VALUE );
switch(evCode) {
UNPACK_VALUE(EC_COMPLETE);
UNPACK_VALUE(EC_USERABORT);
UNPACK_VALUE(EC_ERRORABORT);
UNPACK_VALUE(EC_TIME);
UNPACK_VALUE(EC_REPAINT);
UNPACK_VALUE(EC_STREAM_ERROR_STOPPED);
UNPACK_VALUE(EC_STREAM_ERROR_STILLPLAYING);
UNPACK_VALUE(EC_ERROR_STILLPLAYING);
UNPACK_VALUE(EC_PALETTE_CHANGED);
UNPACK_VALUE(EC_VIDEO_SIZE_CHANGED);
UNPACK_VALUE(EC_QUALITY_CHANGE);
UNPACK_VALUE(EC_SHUTTING_DOWN);
UNPACK_VALUE(EC_CLOCK_CHANGED);
UNPACK_VALUE(EC_PAUSED);
UNPACK_VALUE(EC_OPENING_FILE);
UNPACK_VALUE(EC_BUFFERING_DATA);
UNPACK_VALUE(EC_FULLSCREEN_LOST);
UNPACK_VALUE(EC_ACTIVATE);
UNPACK_VALUE(EC_NEED_RESTART);
UNPACK_VALUE(EC_WINDOW_DESTROYED);
UNPACK_VALUE(EC_DISPLAY_CHANGED);
UNPACK_VALUE(EC_STARVATION);
UNPACK_VALUE(EC_OLE_EVENT);
UNPACK_VALUE(EC_NOTIFY_WINDOW);
UNPACK_VALUE(EC_STREAM_CONTROL_STOPPED);
UNPACK_VALUE(EC_STREAM_CONTROL_STARTED);
UNPACK_VALUE(EC_END_OF_SEGMENT);
UNPACK_VALUE(EC_SEGMENT_STARTED);
UNPACK_VALUE(EC_LENGTH_CHANGED);
UNPACK_VALUE(EC_DEVICE_LOST);
UNPACK_VALUE(EC_SAMPLE_NEEDED);
UNPACK_VALUE(EC_PROCESSING_LATENCY);
UNPACK_VALUE(EC_SAMPLE_LATENCY);
UNPACK_VALUE(EC_SCRUB_TIME);
UNPACK_VALUE(EC_STEP_COMPLETE);
UNPACK_VALUE(EC_TIMECODE_AVAILABLE);
UNPACK_VALUE(EC_EXTDEVICE_MODE_CHANGE);
UNPACK_VALUE(EC_STATE_CHANGE);
UNPACK_VALUE(EC_GRAPH_CHANGED);
UNPACK_VALUE(EC_CLOCK_UNSET);
UNPACK_VALUE(EC_VMR_RENDERDEVICE_SET);
UNPACK_VALUE(EC_VMR_SURFACE_FLIPPED);
UNPACK_VALUE(EC_VMR_RECONNECTION_FAILED);
UNPACK_VALUE(EC_PREPROCESS_COMPLETE);
UNPACK_VALUE(EC_CODECAPI_EVENT);
UNPACK_VALUE(EC_WMT_INDEX_EVENT);
UNPACK_VALUE(EC_WMT_EVENT);
UNPACK_VALUE(EC_BUILT);
UNPACK_VALUE(EC_UNBUILT);
UNPACK_VALUE(EC_SKIP_FRAMES);
UNPACK_VALUE(EC_PLEASE_REOPEN);
UNPACK_VALUE(EC_STATUS);
UNPACK_VALUE(EC_MARKER_HIT);
UNPACK_VALUE(EC_LOADSTATUS);
UNPACK_VALUE(EC_FILE_CLOSED);
UNPACK_VALUE(EC_ERRORABORTEX);
//UNPACK_VALUE(EC_NEW_PIN);
//UNPACK_VALUE(EC_RENDER_FINISHED);
UNPACK_VALUE(EC_EOS_SOON);
UNPACK_VALUE(EC_CONTENTPROPERTY_CHANGED);
UNPACK_VALUE(EC_BANDWIDTHCHANGE);
UNPACK_VALUE(EC_VIDEOFRAMEREADY);
UNPACK_VALUE(EC_BG_AUDIO_CHANGED);
UNPACK_VALUE(EC_BG_ERROR);
};
#undef UNPACK_VALUE
return _T("UNKNOWN");
}
#endif
/////////////////////////////////////////////////////////////////////////////
// CMainFrame construction/destruction
#pragma warning(disable : 4355)
CMainFrame::CMainFrame() :
m_iMediaLoadState(MLS_CLOSED),
m_iPlaybackMode(PM_NONE),
m_iSpeedLevel(0),
m_rtDurationOverride(-1),
m_fFullScreen(false),
m_fFirstFSAfterLaunchOnFS(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),
m_pFullscreenWnd(NULL),
m_pVideoWnd(NULL),
m_bRemainingTime(false),
m_nCurSubtitle(-1),
m_lSubtitleShift(0),
m_bToggleShader(false),
m_nStepForwardCount(0),
m_rtStepForwardStart(0),
m_bToggleShaderScreenSpace(false),
m_bInOptions(false),
m_lCurrentChapter(0),
m_lChapterStartTime(0xFFFFFFFF),
m_pTaskbarList(NULL),
m_pGraphThread(NULL),
m_bOpenedThruThread(false)
{
m_Lcd.SetVolumeRange(0, 100);
m_LastSaveTime.QuadPart = 0;
}
CMainFrame::~CMainFrame()
{
// m_owner.DestroyWindow();
//delete m_pFullscreenWnd; // double delete see CMainFrame::OnDestroy
}
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
BOOL bResult = m_wndStatusBar.Create(this);
if(bResult) {
bResult = m_wndStatsBar.Create(this);
}
if(bResult) {
bResult = m_wndInfoBar.Create(this);
}
if(bResult) {
bResult = m_wndToolBar.Create(this);
}
if(bResult) {
bResult = m_wndSeekBar.Create(this);
}
if(!bResult) {
TRACE0("Failed to create all control bars\n");
return -1; // fail to create
}
m_pFullscreenWnd = DNew CFullscreenWnd(this);
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(GetRecentFile());
m_wndEditListEditor.Create(this);
m_wndEditListEditor.SetBarStyle(m_wndEditListEditor.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
m_wndEditListEditor.EnableDocking(CBRS_ALIGN_ANY);
LoadControlBar(&m_wndEditListEditor, AFX_IDW_DOCKBAR_RIGHT);
m_wndEditListEditor.SetHeight(100);
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_wndNavigationBar.Create(this);
m_wndNavigationBar.SetBarStyle(m_wndNavigationBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
m_wndNavigationBar.EnableDocking(CBRS_ALIGN_LEFT|CBRS_ALIGN_RIGHT);
LoadControlBar(&m_wndNavigationBar, 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.nCmdlnWebServerPort != 0) {
if(s.nCmdlnWebServerPort > 0) {
StartWebServer(s.nCmdlnWebServerPort);
} else if(s.fEnableWebServer) {
StartWebServer(s.nWebServerPort);
}
}
// Casimir666 : reload Shaders
{
CString strList = s.strShaderList;
CString strRes;
int curPos= 0;
strRes = strList.Tokenize (_T("|"), curPos);
while (strRes != _T("")) {
m_shaderlabels.AddTail (strRes);
strRes = strList.Tokenize(_T("|"),curPos);
}
}
{
CString strList = s.strShaderListScreenSpace;
CString strRes;
int curPos= 0;
strRes = strList.Tokenize (_T("|"), curPos);
while (strRes != _T("")) {
m_shaderlabelsScreenSpace.AddTail (strRes);
strRes = strList.Tokenize(_T("|"),curPos);
}
}
m_bToggleShader = s.fToggleShader;
m_bToggleShaderScreenSpace = s.fToggleShaderScreenSpace;
#ifdef _WIN64
m_strTitle.Format (L"%s x64 - v%s", ResStr(IDR_MAINFRAME), AfxGetMyApp()->m_strVersion);
#else
m_strTitle.Format (L"%s - v%s", ResStr(IDR_MAINFRAME), AfxGetMyApp()->m_strVersion);
#endif
SetWindowText(m_strTitle);
m_Lcd.SetMediaTitle(LPCTSTR(m_strTitle));
m_OpenFile = false;
SendAPICommand (CMD_CONNECT, L"%d", GetSafeHwnd());
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, (DWORD)-1 );
}
}
if ( m_pFullscreenWnd ) {
if ( m_pFullscreenWnd->IsWindow() ) {
m_pFullscreenWnd->DestroyWindow();
}
delete m_pFullscreenWnd;
}
__super::OnDestroy();
}
void CMainFrame::OnClose()
{
AppSettings& s = AfxGetAppSettings();
// Casimir666 : save shaders list
{
POSITION pos;
CString strList = "";
pos = m_shaderlabels.GetHeadPosition();
while(pos) {
strList += m_shaderlabels.GetAt (pos) + "|";
m_dockingbars.GetNext(pos);
}
s.strShaderList = strList;
}
{
POSITION pos;
CString strList = "";
pos = m_shaderlabelsScreenSpace.GetHeadPosition();
while(pos) {
strList += m_shaderlabelsScreenSpace.GetAt (pos) + "|";
m_dockingbars.GetNext(pos);
}
s.strShaderListScreenSpace = strList;
}
s.fToggleShader = m_bToggleShader;
s.fToggleShaderScreenSpace = m_bToggleShaderScreenSpace;
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 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;
}
LPCTSTR CMainFrame::GetRecentFile()
{
CRecentFileList& MRU = AfxGetAppSettings().MRU;
MRU.ReadList();
for(int i = 0; i < MRU.GetSize(); i++) {
if(!MRU[i].IsEmpty()) {
return MRU[i].GetString();
}
}
return NULL;
}
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
&& pBar != &m_wndNavigationBar
&& pBar != &m_wndPlaylistBar
? SW_SHOW
: SW_HIDE);
if(CSizingControlBar* pSCB = dynamic_cast(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((pBar == &m_wndPlaylistBar) && pApp->GetProfileInt(section, _T("Visible"), FALSE)) {
pBar->ShowWindow(SW_SHOW);
}
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(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, GetModalParent());
PostMessage(WM_NULL);
break;
}
case WM_MOUSEMOVE: {
CString str;
GetWindowText(str);
SetTrayTip(str);
break;
}
default:
break;
}
return 0;
}
LRESULT CMainFrame::OnTaskBarThumbnailsCreate(WPARAM, LPARAM)
{
return CreateThumbnailToolbar();
}
void CMainFrame::ShowTrayIcon(bool fShow)
{
BOOL bWasVisible = ShowWindow(SW_HIDE);
NOTIFYICONDATA tnid;
ZeroMemory(&tnid, sizeof(NOTIFYICONDATA));
tnid.cbSize = sizeof(NOTIFYICONDATA);
tnid.hWnd = m_hWnd;
tnid.uID = IDR_MAINFRAME;
if(fShow) {
if(!m_fTrayIcon) {
tnid.hIcon = (HICON)LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
tnid.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP;
tnid.uCallbackMessage = WM_NOTIFYICON;
StringCchCopy(tnid.szTip, countof(tnid.szTip), TEXT("Media Player Classic"));
Shell_NotifyIcon(NIM_ADD, &tnid);
m_fTrayIcon = true;
}
} else {
if(m_fTrayIcon) {
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;
StringCchCopy(tnid.szTip, countof(tnid.szTip), str);
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) {
bool fEscapeNotAssigned = !assignedToCmd(VK_ESCAPE, false);
if(fEscapeNotAssigned) {
if(m_iMediaLoadState == MLS_LOADED && m_fFullScreen) {
OnViewFullscreen();
PostMessage(WM_COMMAND, ID_PLAY_PAUSE);
return TRUE;
} else if(IsCaptionHidden()) {
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)
{
AppSettings &s = AfxGetAppSettings();
DWORD style = GetStyle();
MENUBARINFO mbi;
memset(&mbi, 0, sizeof(mbi));
mbi.cbSize = sizeof(mbi);
::GetMenuBarInfo(m_hWnd, OBJID_MENU, 0, &mbi);
lpMMI->ptMinTrackSize.x = 16;
if ( !IsMenuHidden() ) {
// Calculate menu's horizontal length in pixels
lpMMI->ptMinTrackSize.x = 10;
CRect r;
for (int i = 0; ::GetMenuItemRect(m_hWnd, mbi.hMenu, i, &r); i++) {
lpMMI->ptMinTrackSize.x += r.Width();
}
}
if ( IsWindow(m_wndToolBar.m_hWnd) && m_wndToolBar.IsVisible() ) {
lpMMI->ptMinTrackSize.x = max( m_wndToolBar.GetMinWidth(), lpMMI->ptMinTrackSize.x );
}
lpMMI->ptMinTrackSize.y = 0;
if ( style & WS_CAPTION ) {
lpMMI->ptMinTrackSize.y += GetSystemMetrics( SM_CYCAPTION );
if(s.iCaptionMenuMode == MODE_SHOWCAPTIONMENU)
lpMMI->ptMinTrackSize.y += GetSystemMetrics( SM_CYMENU ); //(mbi.rcBar.bottom - mbi.rcBar.top);
//else MODE_HIDEMENU
}
if ( style & WS_THICKFRAME ) {
lpMMI->ptMinTrackSize.x += GetSystemMetrics( (style & WS_CAPTION) ? SM_CXSIZEFRAME : SM_CXFIXEDFRAME ) * 2;
lpMMI->ptMinTrackSize.y += GetSystemMetrics( SM_CYSIZEFRAME ) * 2;
}
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; // 2 is a magic value from CSizingControlBar class, i guess this should be GetSystemMetrics( SM_CXBORDER ) or similar
}
}
if (lpMMI->ptMinTrackSize.y<16) lpMMI->ptMinTrackSize.y = 16;
__super::OnGetMinMaxInfo( lpMMI );
}
void CMainFrame::OnMove(int x, int y)
{
__super::OnMove(x, y);
//MoveVideoWindow(); // This isn't needed, based on my limited tests. If it is needed then please add a description the scenario(s) where it is needed.
m_wndView.Invalidate();
WINDOWPLACEMENT wp;
GetWindowPlacement(&wp);
if(!m_fFirstFSAfterLaunchOnFS && !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);
m_OSD.OnSize (nType, cx, cy);
if(nType == SIZE_RESTORED && m_fTrayIcon) {
ShowWindow(SW_SHOW);
}
if(!m_fFirstFSAfterLaunchOnFS && IsWindowVisible() && !m_fFullScreen) {
AppSettings& s = AfxGetAppSettings();
if(nType != SIZE_MAXIMIZED && nType != SIZE_MINIMIZED) {
GetWindowRect(s.rcLastWindowPos);
}
s.nLastWindowType = 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.fLimitWindowProportions)) { // remember that fCtrl is initialized with !!whatever(), same with fLimitWindowProportions
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();
// This doesn't give correct menu pixel size
//MENUBARINFO mbi;
//memset(&mbi, 0, sizeof(mbi));
//mbi.cbSize = sizeof(mbi);
//::GetMenuBarInfo(m_hWnd, OBJID_MENU, 0, &mbi);
if ( style & WS_THICKFRAME ) {
fsize.cx += GetSystemMetrics( SM_CXSIZEFRAME ) * 2;
}
if ( style & WS_CAPTION ) {
fsize.cy += GetSystemMetrics( SM_CYCAPTION );
if(s.iCaptionMenuMode == MODE_SHOWCAPTIONMENU)
fsize.cy += GetSystemMetrics( SM_CYMENU ); //mbi.rcBar.bottom - mbi.rcBar.top;
//else MODE_HIDEMENU
}
if ( style & WS_THICKFRAME ) {
fsize.cy += GetSystemMetrics( SM_CYSIZEFRAME ) * 2;
}
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() && !pCB->IsFloating() ) {
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);
if (m_pFullscreenWnd && m_pFullscreenWnd->IsWindow()) {
MONITORINFO MonitorInfo;
HMONITOR hMonitor;
ZeroMemory (&MonitorInfo, sizeof(MonitorInfo));
MonitorInfo.cbSize = sizeof(MonitorInfo);
hMonitor = MonitorFromWindow (m_pFullscreenWnd->m_hWnd, 0);
if (GetMonitorInfo (hMonitor, &MonitorInfo)) {
CRect MonitorRect = CRect (MonitorInfo.rcMonitor);
m_fullWndSize.cx = MonitorRect.Width();
m_fullWndSize.cy = MonitorRect.Height();
m_pFullscreenWnd->SetWindowPos (NULL,
MonitorRect.left,
MonitorRect.top,
MonitorRect.Width(),
MonitorRect.Height(), SWP_NOZORDER);
MoveVideoWindow();
}
}
if(m_iMediaLoadState == MLS_LOADED) {
if(m_pGraphThread) {
m_pGraphThread->PostThreadMessage(CGraphThread::TM_DISPLAY_CHANGE, 0, 0);
} else {
DisplayChange();
}
}
}
#include
void CMainFrame::OnSysCommand(UINT nID, LPARAM lParam)
{
// Only stop screensaver if video playing; allow for audio only
if ((GetMediaState() == State_Running && !m_fAudioOnly) && (((nID & 0xFFF0) == SC_SCREENSAVE) || ((nID & 0xFFF0) == SC_MONITORPOWER))) {
TRACE(_T("SC_SCREENSAVE, nID = %d, lParam = %d\n"), nID, lParam);
return;
} 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);
if(AfxGetAppSettings().iOnTop)
return;
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);
CMonitors monitors;
if(hMonitor1 && hMonitor2 && ((hMonitor1 != hMonitor2) || (monitors.GetCount()>1))) {
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(ResStr(IDS_MAINFRM_2), 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);
if(uDevice != FAPPCOMMAND_OEM ||
cmd == APPCOMMAND_MEDIA_PLAY || cmd == APPCOMMAND_MEDIA_PAUSE || cmd == APPCOMMAND_MEDIA_CHANNEL_UP ||
cmd == APPCOMMAND_MEDIA_CHANNEL_DOWN || cmd == APPCOMMAND_MEDIA_RECORD ||
cmd == APPCOMMAND_MEDIA_FAST_FORWARD || cmd == APPCOMMAND_MEDIA_REWIND ) {
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::OnRawInput(UINT nInputcode, HRAWINPUT hRawInput)
{
AppSettings& s = AfxGetAppSettings();
UINT nMceCmd = 0;
nMceCmd = AfxGetMyApp()->GetRemoteControlCode (nInputcode, hRawInput);
switch (nMceCmd) {
case MCE_DETAILS :
case MCE_GUIDE :
case MCE_TVJUMP :
case MCE_STANDBY :
case MCE_OEM1 :
case MCE_OEM2 :
case MCE_MYTV :
case MCE_MYVIDEOS :
case MCE_MYPICTURES :
case MCE_MYMUSIC :
case MCE_RECORDEDTV :
case MCE_DVDANGLE :
case MCE_DVDAUDIO :
case MCE_DVDMENU :
case MCE_DVDSUBTITLE :
case MCE_RED :
case MCE_GREEN :
case MCE_YELLOW :
case MCE_BLUE :
case MCE_MEDIA_NEXTTRACK :
case MCE_MEDIA_PREVIOUSTRACK :
POSITION pos = s.wmcmds.GetHeadPosition();
while(pos) {
wmcmd& wc = s.wmcmds.GetNext(pos);
if(wc.appcmd == nMceCmd) {
SendMessage(WM_COMMAND, wc.cmd);
break;
}
}
break;
}
}
LRESULT CMainFrame::OnHotKey(WPARAM wParam, LPARAM lParam)
{
AppSettings& s = AfxGetAppSettings();
BOOL fRet = FALSE;
if (GetActiveWindow() == this || s.fGlobalMedia == TRUE) {
POSITION pos = s.wmcmds.GetHeadPosition();
while(pos) {
wmcmd& wc = s.wmcmds.GetNext(pos);
if (wc.appcmd == wParam && TRUE == SendMessage(WM_COMMAND, wc.cmd)) {
fRet = TRUE;
}
}
}
return fRet;
}
bool g_bNoDuration = false;
bool g_bExternalSubtitleTime = false;
void CMainFrame::OnTimer(UINT_PTR nIDEvent)
{
switch (nIDEvent) {
case TIMER_STREAMPOSPOLLER:
if(m_iMediaLoadState == MLS_LOADED) {
REFERENCE_TIME rtNow = 0, rtDur = 0;
if(GetPlaybackMode() == PM_FILE) {
pMS->GetCurrentPosition(&rtNow);
pMS->GetDuration(&rtDur);
// Casimir666 : autosave subtitle sync after play
if ((m_nCurSubtitle >= 0) && (m_rtCurSubPos != rtNow)) {
if (m_lSubtitleShift != 0) {
if (m_wndSubresyncBar.SaveToDisk()) {
m_OSD.DisplayMessage (OSD_TOPLEFT, ResStr(IDS_AG_SUBTITLES_SAVED), 500);
} else {
m_OSD.DisplayMessage (OSD_TOPLEFT, ResStr(IDS_MAINFRM_4));
}
}
m_nCurSubtitle = -1;
m_lSubtitleShift = 0;
}
if(!m_fEndOfStream) {
AppSettings& s = AfxGetAppSettings();
FILE_POSITION* FilePosition = s.CurrentFilePosition();
if (FilePosition) {
FilePosition->llPosition = rtNow;
LARGE_INTEGER time;
QueryPerformanceCounter(&time);
LARGE_INTEGER freq;
QueryPerformanceFrequency(&freq);
if((time.QuadPart - m_LastSaveTime.QuadPart) >= 30 * freq.QuadPart) { // save every half of minute
m_LastSaveTime = time;
if (s.fKeepHistory && s.fRememberFilePos) {
s.SaveCurrentFilePosition();
}
}
}
}
if(m_rtDurationOverride >= 0) {
rtDur = m_rtDurationOverride;
}
g_bNoDuration = rtDur <= 0;
m_wndSeekBar.Enable(rtDur > 0);
m_wndSeekBar.SetRange(0, rtDur);
m_wndSeekBar.SetPos(rtNow);
m_OSD.SetRange (0, rtDur);
m_OSD.SetPos (rtNow);
m_Lcd.SetMediaRange(0, rtDur);
m_Lcd.SetMediaPos(rtNow);
} else if(GetPlaybackMode() == PM_CAPTURE) {
pMS->GetCurrentPosition(&rtNow);
if(m_fCapturing && m_wndCaptureBar.m_capdlg.m_pMux) {
CComQIPtr pMuxMS = m_wndCaptureBar.m_capdlg.m_pMux;
if(!pMuxMS || FAILED(pMuxMS->GetCurrentPosition(&rtNow))) {
rtNow = 0;
}
}
if(m_rtDurationOverride >= 0) {
rtDur = m_rtDurationOverride;
}
g_bNoDuration = rtDur <= 0;
m_wndSeekBar.Enable(false);
m_wndSeekBar.SetRange(0, rtDur);
m_wndSeekBar.SetPos(rtNow);
m_OSD.SetRange (0, rtDur);
m_OSD.SetPos (rtNow);
m_Lcd.SetMediaRange(0, rtDur);
m_Lcd.SetMediaPos(rtNow);
/*
if(m_fCapturing)
{
if(rtNow > 10000i64*1000*60*60*3)
{
m_wndCaptureBar.m_capdlg.OnRecord();
}
}
*/
}
if(m_pCAP && GetPlaybackMode() != PM_FILE) {
g_bExternalSubtitleTime = true;
if (pDVDI) {
DVD_PLAYBACK_LOCATION2 Location;
if (pDVDI->GetCurrentLocation(&Location) == S_OK) {
double fps = Location.TimeCodeFlags == DVD_TC_FLAG_25fps ? 25.0
: Location.TimeCodeFlags == DVD_TC_FLAG_30fps ? 30.0
: Location.TimeCodeFlags == DVD_TC_FLAG_DropFrame ? 29.97
: 25.0;
LONGLONG rtTimeCode = HMSF2RT(Location.TimeCode, fps);
m_pCAP->SetTime(rtTimeCode);
} else {
m_pCAP->SetTime(/*rtNow*/m_wndSeekBar.GetPos());
}
} else {
// Set rtNow to support DVB subtitle
m_pCAP->SetTime(rtNow);
}
} else {
g_bExternalSubtitleTime = false;
}
}
break;
case TIMER_STREAMPOSPOLLER2:
if (m_iMediaLoadState == MLS_LOADED) {
__int64 start, stop, pos;
m_wndSeekBar.GetRange(start, stop);
pos = m_wndSeekBar.GetPosReal();
GUID tf;
pMS->GetTimeFormat(&tf);
if(GetPlaybackMode() == 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);
if (m_bRemainingTime) {
m_OSD.DisplayMessage(OSD_TOPLEFT, m_wndStatusBar.GetStatusTimer());
}
}
m_wndSubresyncBar.SetTime(pos);
if(m_pCAP && GetMediaState() == State_Paused) {
m_pCAP->Paint(false);
}
}
break;
case 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);
}
}
}
break;
case TIMER_FULLSCREENMOUSEHIDER: {
CPoint p;
GetCursorPos(&p);
CRect r;
GetWindowRect(r);
bool fCursorOutside = !r.PtInRect(p);
if (m_pFullscreenWnd->IsWindow()) {
TRACE ("==> HIDE!\n");
if (!m_bInOptions) {
m_pFullscreenWnd->ShowCursor(false);
}
KillTimer(TIMER_FULLSCREENMOUSEHIDER);
} else {
CWnd* pWnd = WindowFromPoint(p);
if(pWnd && (m_wndView == *pWnd || m_wndView.IsChild(pWnd) || fCursorOutside)) {
m_fHideCursor = true;
SetCursor(NULL);
}
}
}
break;
case 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(ResStr(IDS_AG_FRAMERATE), 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(ResStr(IDS_MAINFRM_6), drawn, dropped);
m_wndStatsBar.SetLine(ResStr(IDS_AG_FRAMES), info);
pQP->get_Jitter(&val);
info.Format(_T("%d ms"), val);
m_wndStatsBar.SetLine(_T("Jitter"), info);
}
if(pBI) {
CAtlList 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(ResStr(IDS_AG_BUFFERS), str);
}
}
CInterfaceList pBRIs;
BeginEnumFilters(pGB, pEF, pBF) {
BeginEnumPins(pBF, pEP, pPin) {
if(CComQIPtr pBRI = pPin) {
pBRIs.AddTail(pBRI);
}
}
EndEnumPins;
if(!pBRIs.IsEmpty()) {
CAtlList 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(GetPlaybackMode() == PM_FILE) {
SetupChapters();
}
if(GetPlaybackMode() == 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(ResStr(IDS_MAINFRM_9),
ulVolume, ulNumOfVolumes,
loc.TitleNum, ulNumOfTitles,
loc.ChapterNum, ulNumOfChapters);
ULONG tsec = (loc.TimeCode.bHours*3600)
+ (loc.TimeCode.bMinutes*60)
+ (loc.TimeCode.bSeconds);
/* This might not always work, such as on resume */
if ( loc.ChapterNum != m_lCurrentChapter ) {
m_lCurrentChapter = loc.ChapterNum;
m_lChapterStartTime = tsec;
} else {
/* If a resume point was used, and the user chapter jumps,
then it might do some funky time jumping. Try to 'fix' the
chapter start time if this happens */
if ( m_lChapterStartTime > tsec ) {
m_lChapterStartTime = tsec;
}
}
}
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(ResStr(IDS_MAINFRM_10),
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 = GetDVDAudioFormatName(AATR);
Audio.Format(ResStr(IDS_MAINFRM_11),
lang,
format,
AATR.dwFrequency,
AATR.bQuantization,
AATR.bNumberOfChannels,
(AATR.bNumberOfChannels > 1 ? ResStr(IDS_MAINFRM_13) : ResStr(IDS_MAINFRM_12)));
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 && !m_fAudioOnly) {
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);
}
// prevent screensaver activate, monitor sleep/turn off after playback
SetThreadExecutionState(ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED);
}
}
break;
case TIMER_STATUSERASER: {
KillTimer(TIMER_STATUSERASER);
m_playingmsg.Empty();
}
break;
}
__super::OnTimer(nIDEvent);
}
static bool SetShutdownPrivilege()
{
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
SetThreadExecutionState (ES_CONTINUOUS);
// 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 || s.fExitAfterPlayback) {
fExit = true;
}
if(s.nCLSwitches&CLSW_STANDBY) {
SetShutdownPrivilege();
SetSystemPowerState(TRUE, FALSE);
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, FALSE);
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;
}
//
// graph event EC_COMPLETE handler
//
bool CMainFrame::GraphEventComplete( )
{
AppSettings& s = AfxGetAppSettings();
FILE_POSITION* FilePosition = s.CurrentFilePosition();
if (FilePosition) {
FilePosition->llPosition = 0;
QueryPerformanceCounter(&m_LastSaveTime);
if (s.fKeepHistory && s.fRememberFilePos) {
s.SaveCurrentFilePosition();
}
}
if(m_wndPlaylistBar.GetCount() <= 1) {
m_nLoops++;
if(DoAfterPlaybackEvent()) {
return false;
}
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 {
int NextMediaExist = 0;
if (s.fNextInDirAfterPlayback) {
NextMediaExist = SearchInDir(true);
}
if (!s.fNextInDirAfterPlayback || !(NextMediaExist>1)) {
if(s.fRewind) {
SendMessage(WM_COMMAND, ID_PLAY_STOP);
} else {
m_fEndOfStream = true;
SendMessage(WM_COMMAND, ID_PLAY_PAUSE);
}
m_OSD.ClearMessage();
if(m_fFullScreen && s.fExitFullScreenAtTheEnd) {
OnViewFullscreen();
}
}
if (s.fNextInDirAfterPlayback && !NextMediaExist) {
m_OSD.DisplayMessage(OSD_TOPLEFT, ResStr(IDS_NO_MORE_MEDIA));
// Don't move it. Else OSD message "Pause" will rewrite this message.
}
}
} else if(m_wndPlaylistBar.GetCount() > 1) {
if(m_wndPlaylistBar.IsAtEnd()) {
if(DoAfterPlaybackEvent()) {
return false;
}
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) {
s.nCLSwitches |= CLSW_OPEN; // HACK
PostMessage(WM_COMMAND, ID_NAVIGATE_SKIPFORWARD);
} else {
m_fEndOfStream = true;
PostMessage(WM_COMMAND, ID_PLAY_PAUSE);
}
}
}
return true;
}
//
// our WM_GRAPHNOTIFY handler
//
#include
LRESULT CMainFrame::OnGraphNotify(WPARAM wParam, LPARAM lParam)
{
AppSettings& s = AfxGetAppSettings();
HRESULT hr = S_OK;
LONG evCode;
LONG_PTR evParam1, evParam2;
while(pME && SUCCEEDED(pME->GetEvent(&evCode, &evParam1, &evParam2, 0))) {
#ifdef _DEBUG
TRACE("--> CMainFrame::OnGraphNotify on thread: %d; event: 0x%08x (%ws)\n", GetCurrentThreadId(), evCode, GetEventString(evCode));
#endif
CString str;
if(m_fCustomGraph) {
if(EC_BG_ERROR == evCode) {
str = CString((char*)evParam1);
}
}
if (!m_fFrameSteppingActive) {
m_nStepForwardCount = 0;
}
hr = pME->FreeEventParams(evCode, evParam1, evParam2);
switch(evCode) {
case EC_COMPLETE:
if (!GraphEventComplete()) {
return hr;
}
break;
case EC_ERRORABORT:
TRACE(_T("\thr = %08x\n"), (HRESULT)evParam1);
break;
case EC_BUFFERING_DATA:
TRACE(_T("\t%d, %d\n"), (HRESULT)evParam1, evParam2);
m_fBuffering = ((HRESULT)evParam1 != S_OK);
break;
case EC_STEP_COMPLETE:
if(m_fFrameSteppingActive) {
m_nStepForwardCount++;
m_fFrameSteppingActive = false;
pBA->put_Volume(m_VolumeBeforeFrameStepping);
}
break;
case EC_DEVICE_LOST:
if(GetPlaybackMode() == PM_CAPTURE && evParam2 == 0) {
CComQIPtr pBF = (IUnknown*)evParam1;
if (!pVidCap && pVidCap == pBF || !pAudCap && pAudCap == pBF) {
SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
}
}
break;
case EC_DVD_TITLE_CHANGE: {
// Casimir666 : Save current chapter
DVD_POSITION* DvdPos = s.CurrentDVDPosition();
if (DvdPos) {
DvdPos->lTitle = (DWORD)evParam1;
}
if(GetPlaybackMode() == PM_FILE) {
SetupChapters();
} else if(GetPlaybackMode() == PM_DVD) {
m_iDVDTitle = (DWORD)evParam1;
if(m_iDVDDomain == DVD_DOMAIN_Title) {
CString Domain;
Domain.Format(ResStr(IDS_AG_TITLE), m_iDVDTitle);
m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_DOMAIN), Domain);
}
}
}
break;
case EC_DVD_DOMAIN_CHANGE: {
m_iDVDDomain = (DVD_DOMAIN)evParam1;
CString Domain('-');
switch(m_iDVDDomain) {
case DVD_DOMAIN_FirstPlay:
ULONGLONG llDVDGuid;
Domain = _T("First Play");
if ( s.fShowDebugInfo ) {
m_OSD.DebugMessage(_T("%s"), Domain);
}
if (pDVDI && SUCCEEDED (pDVDI->GetDiscID (NULL, &llDVDGuid))) {
if ( s.fShowDebugInfo ) {
m_OSD.DebugMessage(_T("DVD Title: %d"), s.lDVDTitle);
}
if (s.lDVDTitle != 0) {
s.NewDvd (llDVDGuid);
// Set command line position
hr = pDVDC->PlayTitle(s.lDVDTitle, DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
if ( s.fShowDebugInfo ) {
m_OSD.DebugMessage(_T("PlayTitle: 0x%08X"), hr);
m_OSD.DebugMessage(_T("DVD Chapter: %d"), s.lDVDChapter);
}
if (s.lDVDChapter > 1) {
hr = pDVDC->PlayChapterInTitle(s.lDVDTitle, s.lDVDChapter, DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
if ( s.fShowDebugInfo ) {
m_OSD.DebugMessage(_T("PlayChapterInTitle: 0x%08X"), hr);
}
} else {
// Trick: skip trailers with some DVDs
hr = pDVDC->Resume(DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
if ( s.fShowDebugInfo ) {
m_OSD.DebugMessage(_T("Resume: 0x%08X"), hr);
}
// If the resume call succeeded, then we skip PlayChapterInTitle
// and PlayAtTimeInTitle.
if ( hr == S_OK ) {
// This might fail if the Title is not available yet?
hr = pDVDC->PlayAtTime(&s.DVDPosition,
DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
if ( s.fShowDebugInfo ) {
m_OSD.DebugMessage(_T("PlayAtTime: 0x%08X"), hr);
}
} else {
if ( s.fShowDebugInfo )
m_OSD.DebugMessage(_T("Timecode requested: %02d:%02d:%02d.%03d"),
s.DVDPosition.bHours, s.DVDPosition.bMinutes,
s.DVDPosition.bSeconds, s.DVDPosition.bFrames);
// Always play chapter 1 (for now, until something else dumb happens)
hr = pDVDC->PlayChapterInTitle(s.lDVDTitle, 1,
DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
if ( s.fShowDebugInfo ) {
m_OSD.DebugMessage(_T("PlayChapterInTitle: 0x%08X"), hr);
}
// This might fail if the Title is not available yet?
hr = pDVDC->PlayAtTime(&s.DVDPosition,
DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
if ( s.fShowDebugInfo ) {
m_OSD.DebugMessage(_T("PlayAtTime: 0x%08X"), hr);
}
if ( hr != S_OK ) {
hr = pDVDC->PlayAtTimeInTitle(s.lDVDTitle, &s.DVDPosition,
DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
if ( s.fShowDebugInfo ) {
m_OSD.DebugMessage(_T("PlayAtTimeInTitle: 0x%08X"), hr);
}
}
} // Resume
hr = pDVDC->PlayAtTime(&s.DVDPosition,
DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
if ( s.fShowDebugInfo ) {
m_OSD.DebugMessage(_T("PlayAtTime: %d"), hr);
}
}
m_iDVDTitle = s.lDVDTitle;
s.lDVDTitle = 0;
s.lDVDChapter = 0;
} else if (!s.NewDvd (llDVDGuid) && s.fRememberDVDPos) {
// Set last remembered position (if founded...)
DVD_POSITION* DvdPos = s.CurrentDVDPosition();
pDVDC->PlayTitle(DvdPos->lTitle, DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
pDVDC->Resume(DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
#if 1
if (SUCCEEDED (hr = pDVDC->PlayAtTimeInTitle(
DvdPos->lTitle, &DvdPos->Timecode,
DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL)))
#else
if (SUCCEEDED (hr = pDVDC->PlayAtTime (&DvdPos->Timecode,
DVD_CMD_FLAG_Flush, NULL)))
#endif
{
m_iDVDTitle = DvdPos->lTitle;
}
}
}
break;
case DVD_DOMAIN_VideoManagerMenu:
Domain = _T("Video Manager Menu");
if ( s.fShowDebugInfo ) {
m_OSD.DebugMessage(_T("%s"), Domain);
}
break;
case DVD_DOMAIN_VideoTitleSetMenu:
Domain = _T("Video Title Set Menu");
if ( s.fShowDebugInfo ) {
m_OSD.DebugMessage(_T("%s"), Domain);
}
break;
case DVD_DOMAIN_Title:
Domain.Format(ResStr(IDS_AG_TITLE), m_iDVDTitle);
if ( s.fShowDebugInfo ) {
m_OSD.DebugMessage(_T("%s"), Domain);
}
DVD_POSITION* DvdPos;
DvdPos = s.CurrentDVDPosition();
if (DvdPos) {
DvdPos->lTitle = m_iDVDTitle;
}
break;
case DVD_DOMAIN_Stop:
Domain = ResStr(IDS_AG_STOP);
if ( s.fShowDebugInfo ) {
m_OSD.DebugMessage(_T("%s"), Domain);
}
break;
default:
Domain = _T("-");
if ( s.fShowDebugInfo ) {
m_OSD.DebugMessage(_T("%s"), Domain);
}
break;
}
m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_DOMAIN), Domain);
#if 0 // UOPs debug traces
if (hr == VFW_E_DVD_OPERATION_INHIBITED) {
ULONG UOPfields = 0;
pDVDI->GetCurrentUOPS(&UOPfields);
CString message;
message.Format( _T("UOP bitfield: 0x%08X; domain: %s"), UOPfields, Domain);
m_OSD.DisplayMessage( OSD_TOPLEFT, message );
} else {
m_OSD.DisplayMessage( OSD_TOPRIGHT, Domain );
}
#endif
MoveVideoWindow(); // AR might have changed
}
break;
case EC_DVD_CURRENT_HMSF_TIME: {
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);
}
g_bNoDuration = rtDur <= 0;
m_wndSeekBar.Enable(rtDur > 0);
m_wndSeekBar.SetRange(0, rtDur);
m_OSD.SetRange (0, rtDur);
m_Lcd.SetMediaRange(0, rtDur);
REFERENCE_TIME rtNow = HMSF2RT(*((DVD_HMSF_TIMECODE*)&evParam1), fps);
// Casimir666 : Save current position in the chapter
DVD_POSITION* DvdPos = s.CurrentDVDPosition();
if (DvdPos) {
memcpy (&DvdPos->Timecode, (void*)&evParam1, sizeof(DVD_HMSF_TIMECODE));
}
m_wndSeekBar.SetPos(rtNow);
m_OSD.SetPos(rtNow);
m_Lcd.SetMediaPos(rtNow);
if(m_pSubClock) {
m_pSubClock->SetTime(rtNow);
}
}
break;
case EC_DVD_ERROR: {
TRACE(_T("\t%d %d\n"), evParam1, evParam2);
CString err;
switch(evParam1) {
case DVD_ERROR_Unexpected:
default:
err = ResStr(IDS_MAINFRM_16);
break;
case DVD_ERROR_CopyProtectFail:
err = ResStr(IDS_MAINFRM_17);
break;
case DVD_ERROR_InvalidDVD1_0Disc:
err = ResStr(IDS_MAINFRM_18);
break;
case DVD_ERROR_InvalidDiscRegion:
err = ResStr(IDS_MAINFRM_19);
break;
case DVD_ERROR_LowParentalLevel:
err = ResStr(IDS_MAINFRM_20);
break;
case DVD_ERROR_MacrovisionFail:
err = ResStr(IDS_MAINFRM_21);
break;
case DVD_ERROR_IncompatibleSystemAndDecoderRegions:
err = ResStr(IDS_MAINFRM_22);
break;
case DVD_ERROR_IncompatibleDiscAndDecoderRegions:
err = ResStr(IDS_MAINFRM_23);
break;
}
SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
m_closingmsg = err;
}
break;
case EC_DVD_WARNING:
TRACE(_T("\t%d %d\n"), evParam1, evParam2);
break;
case EC_VIDEO_SIZE_CHANGED: {
TRACE(_T("\t%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(s.fRememberZoomLevel
&& !(m_fFullScreen || wp.showCmd == SW_SHOWMAXIMIZED || wp.showCmd == SW_SHOWMINIMIZED)) {
ZoomVideoWindow();
} else {
MoveVideoWindow();
}
}
break;
case EC_LENGTH_CHANGED: {
__int64 rtDur = 0;
pMS->GetDuration(&rtDur);
m_wndPlaylistBar.SetCurTime(rtDur);
}
break;
case EC_BG_AUDIO_CHANGED:
if(m_fCustomGraph) {
int nAudioChannels = evParam1;
m_wndStatusBar.SetStatusBitmap(nAudioChannels == 1 ? IDB_MONO
: nAudioChannels >= 2 ? IDB_STEREO
: IDB_NOAUDIO);
}
break;
case EC_BG_ERROR:
if(m_fCustomGraph) {
SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
m_closingmsg = !str.IsEmpty() ? str : _T("Unspecified graph error");
m_wndPlaylistBar.SetCurValid(false);
return hr;
}
break;
case EC_DVD_PLAYBACK_RATE_CHANGE:
if(m_fCustomGraph && s.AutoChangeFullscrRes.bEnabled &&
m_fFullScreen && m_iDVDDomain == DVD_DOMAIN_Title) {
AutoChangeMonitorMode();
}
break;
}
}
return hr;
}
LRESULT CMainFrame::OnResetDevice( WPARAM wParam, LPARAM lParam )
{
OAFilterState fs = State_Stopped;
pMC->GetState(0, &fs);
if(fs == State_Running) {
pMC->Pause();
}
BOOL bResult = false;
if (m_bOpenedThruThread) {
CAMEvent e;
m_pGraphThread->PostThreadMessage(CGraphThread::TM_RESET, (WPARAM)&bResult, (LPARAM)&e);
e.Wait();
} else {
ResetDevice();
}
if(fs == State_Running) {
pMC->Run();
}
return S_OK;
}
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 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;
if (m_pFullscreenWnd->IsWindow()) {
m_pFullscreenWnd->GetClientRect(r);
} else {
m_wndView.GetClientRect(r);
m_wndView.MapWindowPoints(this, &r);
}
if(id != wmcmd::WDOWN && id != wmcmd::WUP && !r.PtInRect(point)) {
return FALSE;
}
BOOL ret = FALSE;
WORD cmd = assignedToCmd(id);
if(cmd) {
SendMessage(WM_COMMAND, cmd);
ret = TRUE;
}
return ret;
}
static bool s_fLDown = false;
void CMainFrame::OnLButtonDown(UINT nFlags, CPoint point)
{
if (!m_pFullscreenWnd->IsWindow() || !m_OSD.OnLButtonDown (nFlags, point)) {
SetFocus();
bool fClicked = false;
if(GetPlaybackMode() == 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 = !assignedToCmd(wmcmd::LDOWN);
if(!m_fFullScreen && ((IsCaptionHidden() && AfxGetAppSettings().nCS<=CS_SEEKBAR) || 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 (!m_pFullscreenWnd->IsWindow() || !m_OSD.OnLButtonUp (nFlags, 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)
{
// Waffs : ignore mousemoves when entering fullscreen
if (m_lastMouseMove.x == -1 && m_lastMouseMove.y == -1) {
m_lastMouseMove.x = point.x;
m_lastMouseMove.y = point.y;
}
if (!m_OSD.OnMouseMove (nFlags, point)) {
if(GetPlaybackMode() == PM_DVD) {
CPoint vp = point - m_wndView.GetVideoRect().TopLeft();
pDVDC->SelectAtPosition(vp);
}
CSize diff = m_lastMouseMove - point;
AppSettings& s = AfxGetAppSettings();
if (m_pFullscreenWnd->IsWindow() && (abs(diff.cx)+abs(diff.cy)) >= 1) {
// TRACE ("==> SHOW!\n");
m_pFullscreenWnd->ShowCursor(true);
// Casimir666 : hide the cursor if we are not in the DVD menu
if ((GetPlaybackMode() == PM_FILE) || (GetPlaybackMode() == PM_DVD)) {
KillTimer(TIMER_FULLSCREENMOUSEHIDER);
SetTimer(TIMER_FULLSCREENMOUSEHIDER, 2000, NULL);
}
} else if(m_fFullScreen && (abs(diff.cx)+abs(diff.cy)) >= 1) {
int nTimeOut = s.nShowBarsWhenFullScreenTimeOut;
if(nTimeOut < 0) {
m_fHideCursor = false;
if(s.fShowBarsWhenFullScreen) {
ShowControls(s.nCS);
if (GetPlaybackMode() == PM_CAPTURE && !s.fHideNavigation && s.iDefaultCaptureDevice == 1) {
m_wndNavigationBar.m_navdlg.UpdateElementList();
m_wndNavigationBar.ShowControls(this, TRUE);
}
}
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 size = pNext->CalcFixedLayout(FALSE, TRUE);
if(s.nCS&i) {
r.top -= size.cy;
}
}
// HACK: the controls would cover the menu too early hiding some buttons
if(GetPlaybackMode() == 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(s.fShowBarsWhenFullScreen) {
ShowControls(s.nCS);
}
} else {
if(s.fShowBarsWhenFullScreen) {
ShowControls(CS_NONE, false);
}
}
// PM_CAPTURE: Left Navigation panel for switching channels
if (GetPlaybackMode() == PM_CAPTURE && !s.fHideNavigation && s.iDefaultCaptureDevice == 1) {
CRect rLeft;
GetClientRect(rLeft);
rLeft.right = rLeft.left;
CSize size = m_wndNavigationBar.CalcFixedLayout(FALSE, TRUE);
rLeft.right += size.cx;
m_fHideCursor = false;
if(rLeft.PtInRect(point)) {
if(s.fShowBarsWhenFullScreen) {
m_wndNavigationBar.m_navdlg.UpdateElementList();
m_wndNavigationBar.ShowControls(this, TRUE);
}
} else {
if(s.fShowBarsWhenFullScreen) {
m_wndNavigationBar.ShowControls(this, FALSE);
}
}
}
SetTimer(TIMER_FULLSCREENMOUSEHIDER, 2000, NULL);
} else {
m_fHideCursor = false;
if(s.fShowBarsWhenFullScreen) {
ShowControls(s.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 ((IsCaptionHidden()) && nHitTest == HTCLIENT) ? HTCAPTION : nHitTest;
}
void CMainFrame::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
bool Shift_State = !!(::GetKeyState(VK_SHIFT)&0x8000);
if(AfxGetAppSettings().fFastSeek)
Shift_State = !Shift_State;
if(pScrollBar->IsKindOf(RUNTIME_CLASS(CVolumeCtrl))) {
OnPlayVolume(0);
} else if(pScrollBar->IsKindOf(RUNTIME_CLASS(CPlayerSeekBar)) && m_iMediaLoadState == MLS_LOADED) {
SeekTo(m_wndSeekBar.GetPos(), Shift_State);
} else if (m_pVideoWnd == m_pVideoWnd) {
SeekTo(m_OSD.GetPos(), Shift_State);
}
__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(str == ResStr(IDS_RECENT_FILES_POPUP)) {
SetupRecentFilesSubMenu();
pSubMenu = &m_recentfiles;
}
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 transl;
//if(transl.IsEmpty())
{
transl[ResStr(IDS_AG_NAVIGATE)] = IDS_NAVIGATE_POPUP;
transl[ResStr(IDS_AG_OPEN_DISC)] = IDS_OPENCDROM_POPUP;
transl[ResStr(IDS_AG_FILTERS)] = IDS_FILTERS_POPUP;
transl[_T("Audio")] = IDS_AUDIO_POPUP;
transl[ResStr(IDS_AG_SUBTITLES)] = IDS_SUBTITLES_POPUP;
transl[ResStr(IDS_MAINFRM_28)] = IDS_AUDIOLANGUAGE_POPUP;
transl[ResStr(IDS_MAINFRM_29)] = IDS_SUBTITLELANGUAGE_POPUP;
transl[ResStr(IDS_AG_VIDEO_ANGLE)] = IDS_VIDEOANGLE_POPUP;
transl[ResStr(IDS_AG_JUMP_TO)] = IDS_JUMPTO_POPUP;
transl[ResStr(IDS_AG_FAVORITES)] = IDS_FAVORITES_POPUP;
transl[ResStr(IDS_AG_SHADERS)] = IDS_SHADER_POPUP;
transl[ResStr(IDS_AG_VIDEO_FRAME)] = IDS_VIDEOFRAME_POPUP;
transl[ResStr(IDS_AG_PANSCAN)] = IDS_PANSCAN_POPUP;
transl[ResStr(IDS_AG_ASPECT_RATIO)] = IDS_ASPECTRATIO_POPUP;
transl[_T("Zoom")] = IDS_ZOOM_POPUP;
//transl[ResStr(IDS_RECENT_FILES_POPUP)] = IDS_RECENT_FILES_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/*GetPlaybackMode() == PM_DVD *//*|| (GetPlaybackMode() == 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_RECENT_FILES_POPUP)) {
SetupRecentFilesSubMenu();
pSubMenu = &m_recentfiles;
} 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_RECENT_FILE_START && nID <= ID_RECENT_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;
}
AppSettings& s = AfxGetAppSettings();
// Do not show popup menu in D3D fullscreen for Sync Renderer. It has several adverse effects.
if (IsD3DFullScreenMode() && s.iDSVideoRendererType == VIDRNDT_DS_SYNC) {
return FALSE;
}
KillTimer(TIMER_FULLSCREENMOUSEHIDER);
m_fHideCursor = false;
CPoint point;
GetCursorPos(&point);
MSG msg;
pMenu->TrackPopupMenu(TPM_RIGHTBUTTON|TPM_NOANIMATION, point.x+1, point.y+1, this);
PeekMessage(&msg, this->m_hWnd, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_REMOVE); //remove the click LMB, which closes the popup menu
return TRUE;
}
void CMainFrame::OnMenuPlayerShort()
{
if(IsMenuHidden() || m_pFullscreenWnd->IsWindow()) {
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));
if((AfxGetAppSettings().fUseWin7TaskBar) && (m_pTaskbarList)) {
m_pTaskbarList->SetProgressState(m_hWnd, TBPF_INDETERMINATE);
}
} 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(ResStr(IDS_MAINFRM_37), lDropped + lNotDropped, lDropped);
msg += str;
}
}
CComPtr pPin;
if(SUCCEEDED(pCGB->FindPin(m_wndCaptureBar.m_capdlg.m_pDst, PINDIR_INPUT, NULL, NULL, FALSE, 0, &pPin))) {
LONGLONG size = 0;
if(CComQIPtr 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(ResStr(IDS_MAINFRM_38), size/1024);
} else { //if(size < 1024i64*1024*1024)
str.Format(ResStr(IDS_MAINFRM_39), 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(ResStr(IDS_MAINFRM_40), FreeBytesAvailable.QuadPart/1024);
} else { //if(FreeBytesAvailable.QuadPart < 1024i64*1024*1024)
str.Format(ResStr(IDS_MAINFRM_41), FreeBytesAvailable.QuadPart/1024/1024);
}
msg += str;
}
if(m_wndCaptureBar.m_capdlg.m_pMux) {
__int64 pos = 0;
CComQIPtr 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 pVB = m_wndCaptureBar.m_capdlg.m_pVidBuffer) {
nFreeVidBuffers = pVB->GetFreeBuffers();
}
if(CComQIPtr pAB = m_wndCaptureBar.m_capdlg.m_pAudBuffer) {
nFreeAudBuffers = pAB->GetFreeBuffers();
}
CString str;
str.Format(ResStr(IDS_MAINFRM_42), nFreeVidBuffers, nFreeAudBuffers);
msg += str;
}
}
} else if(m_fBuffering) {
BeginEnumFilters(pGB, pEF, pBF) {
if(CComQIPtr 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();
CString UI_Text =
!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("");
if((!m_fAudioOnly) && (UI_Text == ResStr(IDS_CONTROLS_PLAYING))) {
CString DXVA_Text = GetDXVADecoderDescription();
if(!(_T("Not using DXVA")==DXVA_Text) || (_T("Unknown")==DXVA_Text)) {
UI_Text += _T(" [DXVA]");
}
}
pCmdUI->SetText(UI_Text);
} else if(m_iMediaLoadState == MLS_CLOSING) {
pCmdUI->SetText(ResStr(IDS_CONTROLS_CLOSING));
if((AfxGetAppSettings().fUseWin7TaskBar) && (m_pTaskbarList)) {
m_pTaskbarList->SetProgressState(m_hWnd, TBPF_INDETERMINATE);
}
} else {
pCmdUI->SetText(m_closingmsg);
}
}
void CMainFrame::OnFilePostOpenmedia()
{
OpenSetupInfoBar();
OpenSetupStatsBar();
OpenSetupStatusBar();
// OpenSetupToolBar();
OpenSetupCaptureBar();
__int64 rtDur = 0;
pMS->GetDuration(&rtDur);
m_wndPlaylistBar.SetCurTime(rtDur);
if(GetPlaybackMode() == PM_CAPTURE) {
ShowControlBar(&m_wndSubresyncBar, FALSE, TRUE);
// ShowControlBar(&m_wndPlaylistBar, FALSE, TRUE);
// ShowControlBar(&m_wndCaptureBar, TRUE, TRUE);
}
m_nCurSubtitle = -1;
m_lSubtitleShift = 0;
if(m_pCAP) {
m_pCAP->SetSubtitleDelay(0);
}
SetLoadState (MLS_LOADED);
AppSettings& s = AfxGetAppSettings();
// 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);
// Workaround to avoid MadVR freezing when switching channels in PM_CAPTURE mode:
if(IsWindowVisible() && s.fRememberZoomLevel
&& !(m_fFullScreen || wp.showCmd == SW_SHOWMAXIMIZED || wp.showCmd == SW_SHOWMINIMIZED)
&& GetPlaybackMode() == PM_CAPTURE && s.iDSVideoRendererType == VIDRNDT_DS_MADVR) {
ShowWindow(SW_MAXIMIZE);
wp.showCmd = SW_SHOWMAXIMIZED;
}
// restore magnification
if(IsWindowVisible() && s.fRememberZoomLevel
&& !(m_fFullScreen || wp.showCmd == SW_SHOWMAXIMIZED || wp.showCmd == SW_SHOWMINIMIZED)) {
ZoomVideoWindow(false);
}
}
// Waffs : PnS command line
if(!s.strPnSPreset.IsEmpty()) {
for(int i = 0; i < s.m_pnspresets.GetCount(); i++) {
int j = 0;
CString str = s.m_pnspresets[i];
CString label = str.Tokenize(_T(","), j);
if(s.strPnSPreset == label) {
OnViewPanNScanPresets(i+ID_PANNSCAN_PRESETS_START);
}
}
s.strPnSPreset.Empty();
}
SendNowPlayingToMSN();
SendNowPlayingTomIRC();
SendNowPlayingToApi();
}
void CMainFrame::OnUpdateFilePostOpenmedia(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_iMediaLoadState == MLS_LOADING);
}
void CMainFrame::OnFilePostClosemedia()
{
if (IsD3DFullScreenMode()) {
KillTimer(TIMER_FULLSCREENMOUSEHIDER);
KillTimer(TIMER_FULLSCREENCONTROLBARHIDER);
m_fHideCursor = false;
}
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 (AfxGetAppSettings().fEnableEDLEditor) {
m_wndEditListEditor.CloseFile();
}
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());
}
RecalcLayout();
SetWindowText(m_strTitle);
m_Lcd.SetMediaTitle(LPCTSTR(m_strTitle));
SetAlwaysOnTop(AfxGetAppSettings().iOnTop);
// this will prevent any further UI updates on the dynamically added menu items
SetupFiltersSubMenu();
SetupAudioSwitcherSubMenu();
SetupSubtitlesSubMenu();
SetupNavAudioSubMenu();
SetupNavSubtitleSubMenu();
SetupNavAngleSubMenu();
SetupNavChaptersSubMenu();
SetupFavoritesSubMenu();
SetupRecentFilesSubMenu();
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 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) {
nID = m_iAudioStreams.GetAt(m_iAudioStreams.FindIndex(nID)); // remember that the audio streams are reordered according to user preference, so have to figure out which stream from the original order was clicked
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)) {
long stream_index = (i+(nID==0?1:cStreams-1))%cStreams;
pSS->Enable(stream_index, AMSTREAMSELECTENABLE_ENABLE);
if(SUCCEEDED(pSS->Info(stream_index, &pmt, &dwFlags, &lcid, &dwGroup, &pszName, NULL, NULL))) {
CString strMessage = ResStr(IDS_AUDIO_STREAM);
strMessage.Append(pszName);
m_OSD.DisplayMessage (OSD_TOPLEFT, strMessage);
if(pmt) {
DeleteMediaType(pmt);
}
if(pszName) {
CoTaskMemFree(pszName);
}
}
break;
}
}
} else if(GetPlaybackMode() == PM_FILE) {
SendMessage(WM_COMMAND, ID_OGM_AUDIO_NEXT+nID);
} else if(GetPlaybackMode() == 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(true);
SetFocus();
} else if(GetPlaybackMode() == PM_FILE) {
SendMessage(WM_COMMAND, ID_OGM_SUB_NEXT+nID);
} else if(GetPlaybackMode() == 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) {
if (m_iSubtitleSel == -1) {
m_iSubtitleSel = 0;
} else {
m_iSubtitleSel ^= 0x80000000;
}
UpdateSubtitle(true);
SetFocus();
AfxGetAppSettings().fEnableSubtitles = !(m_iSubtitleSel & 0x80000000);
} else if(GetPlaybackMode() == 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 pSS = FindSourceSelectableFilter();
if(!pSS) {
return;
}
CAtlArray 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) {
int nNewStream = snds[(iSel+(nID==0?1:cnt-1))%cnt];
pSS->Enable(nNewStream, AMSTREAMSELECTENABLE_ENABLE);
AM_MEDIA_TYPE* pmt = NULL;
DWORD dwFlags = 0;
LCID lcid = 0;
DWORD dwGroup = 0;
WCHAR* pszName = NULL;
if(SUCCEEDED(pSS->Info(nNewStream, &pmt, &dwFlags, &lcid, &dwGroup, &pszName, NULL, NULL))) {
CString strMessage;
CString audio_stream = pszName;
int k = audio_stream.Find(_T("Audio - "));
if(k>=0) {
audio_stream = audio_stream.Right(audio_stream.GetLength() - k - 8);
}
strMessage.Format (_T("%s%s"), ResStr(IDS_AUDIO_STREAM), audio_stream);
m_OSD.DisplayMessage (OSD_TOPLEFT, strMessage);
if(pmt) {
DeleteMediaType(pmt);
}
if(pszName) {
CoTaskMemFree(pszName);
}
}
}
}
}
void CMainFrame::OnOgmSub(UINT nID)
{
nID -= ID_OGM_SUB_NEXT;
if(m_iMediaLoadState != MLS_LOADED) {
return;
}
CComQIPtr pSS = FindSourceSelectableFilter();
if(!pSS) {
return;
}
CArray 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) {
int nNewStream = subs[(iSel+(nID==0?1:cnt-1))%cnt];
pSS->Enable(nNewStream, AMSTREAMSELECTENABLE_ENABLE);
AM_MEDIA_TYPE* pmt = NULL;
DWORD dwFlags = 0;
LCID lcid = 0;
DWORD dwGroup = 0;
WCHAR* pszName = NULL;
if(SUCCEEDED(pSS->Info(nNewStream, &pmt, &dwFlags, &lcid, &dwGroup, &pszName, NULL, NULL))) {
CString lang;
CString strMessage;
if (lcid == 0) {
lang = pszName;
} else {
int len = GetLocaleInfo(lcid, LOCALE_SENGLANGUAGE, lang.GetBuffer(64), 64);
lang.ReleaseBufferSetLength(max(len-1, 0));
}
strMessage.Format (ResStr(IDS_MAINFRM_45), lang, _T(""));
m_OSD.DisplayMessage (OSD_TOPLEFT, strMessage);
if(pmt) {
DeleteMediaType(pmt);
}
if(pszName) {
CoTaskMemFree(pszName);
}
}
}
}
}
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)
{
HRESULT hr;
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) {
DVD_AudioAttributes AATR;
UINT nNextStream = (nCurrentStream+(nID==0?1:nStreamsAvailable-1))%nStreamsAvailable;
hr = pDVDC->SelectAudioStream(nNextStream, DVD_CMD_FLAG_Block, NULL);
if (SUCCEEDED(pDVDI->GetAudioAttributes(nNextStream, &AATR))) {
CString lang;
CString strMessage;
int len = GetLocaleInfo(AATR.Language, LOCALE_SENGLANGUAGE, lang.GetBuffer(64), 64);
lang.ReleaseBufferSetLength(max(len-1, 0));
strMessage.Format (_T("%s%s - %s %s"), ResStr(IDS_AUDIO_STREAM), lang, GetDVDAudioFormatName(AATR), FAILED(hr)?ResStr(IDS_AG_ERROR):_T(""));
m_OSD.DisplayMessage (OSD_TOPLEFT, strMessage);
}
}
}
}
void CMainFrame::OnDvdSub(UINT nID)
{
HRESULT hr;
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) {
// UINT nNextStream = (ulCurrentStream+(nID==0?1:ulStreamsAvailable-1))%ulStreamsAvailable;
int nNextStream;
if (!bIsDisabled) {
nNextStream = ulCurrentStream+ (nID==0?1:-1);
} else {
nNextStream = (nID==0?0:ulStreamsAvailable-1);
}
if (!bIsDisabled && ((nNextStream < 0) || (nNextStream >= ulStreamsAvailable))) {
pDVDC->SetSubpictureState(FALSE, DVD_CMD_FLAG_Block, NULL);
m_OSD.DisplayMessage (OSD_TOPLEFT, ResStr(IDS_MAINFRM_44));
} else {
hr = pDVDC->SelectSubpictureStream(nNextStream, DVD_CMD_FLAG_Block, NULL);
DVD_SubpictureAttributes SATR;
pDVDC->SetSubpictureState(TRUE, DVD_CMD_FLAG_Block, NULL);
if(SUCCEEDED(pDVDI->GetSubpictureAttributes(nNextStream, &SATR))) {
CString lang;
CString strMessage;
int len = GetLocaleInfo(SATR.Language, LOCALE_SENGLANGUAGE, lang.GetBuffer(64), 64);
lang.ReleaseBufferSetLength(max(len-1, 0));
strMessage.Format (ResStr(IDS_MAINFRM_45), lang, FAILED(hr)?_T("Error"):_T(""));
m_OSD.DisplayMessage (OSD_TOPLEFT, strMessage);
}
}
}
}
}
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 mask;
AfxGetAppSettings().m_Formats.GetFilter(filter, mask);
COpenFileDlg fd(mask, true, NULL, NULL,
OFN_EXPLORER|OFN_ENABLESIZING|OFN_HIDEREADONLY|OFN_ALLOWMULTISELECT|OFN_ENABLEINCLUDENOTIFY|OFN_NOCHANGEDIR,
filter, GetModalParent());
if(fd.DoModal() != IDOK) {
return;
}
CAtlList 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) || m_pFullscreenWnd->IsWindow()) {
return;
}
COpenDlg dlg;
if(dlg.DoModal() != IDOK || dlg.m_fns.GetCount() == 0) {
return;
}
if(!dlg.m_fAppendPlaylist) {
SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
}
ShowWindow(SW_SHOW);
SetForegroundWindow();
if(dlg.m_fAppendPlaylist) {
m_wndPlaylistBar.Append(dlg.m_fns, dlg.m_fMultipleFiles);
return;
}
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 is_dir(CString dirname)
{
WIN32_FIND_DATA w32fd;
HANDLE h = FindFirstFile(dirname, &w32fd);
return (h!=INVALID_HANDLE_VALUE)&&((w32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)!=0);
}
BOOL CMainFrame::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCDS)
{
AppSettings& s = AfxGetAppSettings();
if (s.hMasterWnd) {
ProcessAPICommand(pCDS);
return TRUE;
}
/*
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 cmdln;
while(len-- > 0) {
CString str;
while(pBuff < pBuffEnd && *pBuff) {
str += *pBuff++;
}
pBuff++;
cmdln.AddTail(str);
}
s.ParseCommandLine(cmdln);
if(s.nCLSwitches&CLSW_SLAVE) {
SendAPICommand (CMD_CONNECT, L"%d", GetSafeHwnd());
}
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.m_filters.GetHeadPosition();
while(pos2) {
FilterOverride* f2 = s.m_filters.GetNext(pos2);
if(f2->type == FilterOverride::EXTERNAL && !f2->path.CompareNoCase(f->path)) {
fFound = true;
break;
}
}
if(!fFound) {
CAutoPtr p(f);
s.m_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 p(DNew 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 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 sl;
sl.AddTailList(&s.slFiles);
if(!fMulti) {
sl.AddTailList(&s.slDubs);
}
CHdmvClipInfo ClipInfo;
CString strPlaylistFile;
CAtlList MainPlaylist;
if(!fMulti && is_dir(s.slFiles.GetHead() + _T("\\BDMV")) && SUCCEEDED(ClipInfo.FindMainMovie (s.slFiles.GetHead(), strPlaylistFile, MainPlaylist))) {
SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
fSetForegroundWindow = true;
m_wndPlaylistBar.Empty();
CAutoPtr p(DNew OpenFileData());
p->fns.AddTail(strPlaylistFile);
OpenMedia(p);
} else if(!fMulti && is_dir(s.slFiles.GetHead() + _T("\\VIDEO_TS"))) {
SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
fSetForegroundWindow = true;
CAutoPtr p(DNew OpenDVDData());
if(p) {
p->path = s.slFiles.GetHead();
p->subs.AddTailList(&s.slSubs);
}
OpenMedia(p);
} else {
if(last_run && ((GetTickCount()-last_run)<500)) {
s.nCLSwitches |= CLSW_ADD;
}
last_run = GetTickCount();
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;
}
int CALLBACK BrowseCallbackProc(HWND hwnd,UINT uMsg,LPARAM lp, LPARAM pData)
{
switch(uMsg) {
case BFFM_INITIALIZED:
//Initial directory is set here
SendMessage(hwnd, BFFM_SETSELECTION, TRUE,(LPARAM)(LPCTSTR)AfxGetAppSettings().strDVDPath);
break;
default:
break;
}
return 0;
}
void CMainFrame::OnFileOpendvd()
{
if ((m_iMediaLoadState == MLS_LOADING) || m_pFullscreenWnd->IsWindow()) {
return;
}
/*
SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
SetForegroundWindow();
ShowWindow(SW_SHOW);
CAutoPtr p(DNew OpenDVDData());
if(p)
{
AppSettings& s = AfxGetAppSettings();
if(s.fUseDVDPath && !s.strDVDPath.IsEmpty())
{
p->path = s.strDVDPath;
p->path.Replace('/', '\\');
if(p->path[p->path.GetLength()-1] != '\\') p->path += '\\';
}
}
OpenMedia(p);*/
AppSettings& s = AfxGetAppSettings();
TCHAR path[_MAX_PATH];
CString strTitle = ResStr(IDS_MAINFRM_46);
BROWSEINFO bi;
bi.hwndOwner = m_hWnd;
bi.pidlRoot = NULL;
bi.pszDisplayName = path;
bi.lpszTitle = strTitle;
bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_VALIDATE | BIF_USENEWUI | BIF_NONEWFOLDERBUTTON;
bi.lpfn = BrowseCallbackProc;
bi.lParam = 0;
bi.iImage = 0;
static LPITEMIDLIST iil;
iil = SHBrowseForFolder(&bi);
if(iil) {
CHdmvClipInfo ClipInfo;
CString strPlaylistFile;
CAtlList MainPlaylist;
SHGetPathFromIDList(iil, path);
s.strDVDPath = path;
if (SUCCEEDED (ClipInfo.FindMainMovie (path, strPlaylistFile, MainPlaylist))) {
m_wndPlaylistBar.Empty();
CAutoPtr p(DNew OpenFileData());
p->fns.AddTail(strPlaylistFile);
OpenMedia(p);
} else {
CAutoPtr p(DNew OpenDVDData());
p->path = path;
p->path.Replace('/', '\\');
if(p->path[p->path.GetLength()-1] != '\\') {
p->path += '\\';
}
OpenMedia(p);
}
}
}
void CMainFrame::OnFileOpendevice()
{
AppSettings& s = AfxGetAppSettings();
if(m_iMediaLoadState == MLS_LOADING) {
return;
}
SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
SetForegroundWindow();
ShowWindow(SW_SHOW);
m_wndPlaylistBar.Empty();
CAutoPtr p(DNew OpenDeviceData());
if(p) {
p->DisplayName[0] = s.strAnalogVideo;
p->DisplayName[1] = s.strAnalogAudio;
}
OpenMedia(p);
if (GetPlaybackMode() == PM_CAPTURE && !s.fHideNavigation && m_iMediaLoadState == MLS_LOADED && s.iDefaultCaptureDevice == 1) {
m_wndNavigationBar.m_navdlg.UpdateElementList();
ShowControlBar(&m_wndNavigationBar, !s.fHideNavigation, TRUE);
}
}
void CMainFrame::OnFileOpenCD(UINT nID)
{
nID -= ID_FILE_OPEN_CD_START;
nID++;
for(TCHAR drive = 'C'; drive <= 'Z'; drive++) {
CAtlList 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::OnFileReopen()
{
OpenCurPlaylistItem();
}
void CMainFrame::OnDropFiles(HDROP hDropInfo)
{
SetForegroundWindow();
if(m_wndPlaylistBar.IsWindowVisible()) {
m_wndPlaylistBar.OnDropFiles(hDropInfo);
return;
}
CAtlList 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);
WIN32_FIND_DATA fd = {0};
HANDLE hFind = FindFirstFile(fn, &fd);
if(hFind != INVALID_HANDLE_VALUE) {
if(fd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) {
if(fn[fn.GetLength()-1] != '\\') {
fn += '\\';
}
COpenDirHelper::RecurseAddDir(fn, &sl);
}
FindClose(hFind);
}
}
::DragFinish(hDropInfo);
if(sl.IsEmpty()) {
return;
}
if(sl.GetCount() == 1 && m_iMediaLoadState == MLS_LOADED && m_pCAP) {
ISubStream *pSubStream = NULL;
if(LoadSubtitle(sl.GetHead(), &pSubStream)) {
SetSubtitle(pSubStream); // the subtitle at the insert position according to LoadSubtitle()
CPath p(sl.GetHead());
p.StripPath();
SendStatusMessage(CString((LPCTSTR)p) + ResStr(IDS_MAINFRM_47), 3000);
return;
}
}
m_wndPlaylistBar.Open(sl, true);
OpenCurPlaylistItem();
}
void CMainFrame::OnFileSaveAs()
{
CString ext, in = m_wndPlaylistBar.GetCurFileName(), 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|OFN_NOCHANGEDIR,
ResStr(IDS_MAINFRM_48), GetModalParent(), 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 || GetPlaybackMode() != PM_FILE) {
pCmdUI->Enable(FALSE);
return;
}
CString fn = m_wndPlaylistBar.GetCurFileName();
CString ext = fn.Mid(fn.ReverseFind('.')+1).MakeLower();
if(fn.Find(_T("://")) >= 0) {
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 || IsVMR7InGraph(pGB) || 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(ResStr(IDS_MAINFRM_49), hr);
break;
}
*ppData = DNew BYTE[size];
if(!(*ppData)) {
return false;
}
hr = m_pCAP->GetDIB(*ppData, (DWORD*)&size);
// if(FAILED(hr)) {errmsg.Format(_T("GetDIB failed, hr = %08x"), hr); break;}
if(FAILED(hr)) {
OnPlayPause();
GetMediaState(); // Pause and retry to support ffdshow queuing.
int retry = 0;
while(FAILED(hr) && retry < 20) {
hr = m_pCAP->GetDIB(*ppData, (DWORD*)&size);
if(SUCCEEDED(hr)) {
break;
}
Sleep(1);
retry++;
}
if(FAILED(hr)) {
errmsg.Format(ResStr(IDS_MAINFRM_49), hr);
break;
}
}
} else if (m_pMFVDC) {
// Capture with EVR
BITMAPINFOHEADER bih = {sizeof(BITMAPINFOHEADER)};
BYTE* pDib;
DWORD dwSize;
REFERENCE_TIME rtImage = 0;
hr = m_pMFVDC->GetCurrentImage (&bih, &pDib, &dwSize, &rtImage);
if(FAILED(hr) || dwSize == 0) {
errmsg.Format(ResStr(IDS_MAINFRM_51), hr);
break;
}
size = (long)dwSize+sizeof(BITMAPINFOHEADER);
*ppData = DNew BYTE[size];
if(!(*ppData)) {
return false;
}
memcpy_s (*ppData, size, &bih, sizeof(BITMAPINFOHEADER));
memcpy_s (*ppData+sizeof(BITMAPINFOHEADER), size-sizeof(BITMAPINFOHEADER), pDib, dwSize);
CoTaskMemFree (pDib);
} else {
hr = pBV->GetCurrentImage(&size, NULL);
if(FAILED(hr) || size == 0) {
errmsg.Format(ResStr(IDS_MAINFRM_51), hr);
break;
}
*ppData = DNew BYTE[size];
if(!(*ppData)) {
return false;
}
hr = pBV->GetCurrentImage(&size, (long*)*ppData);
if(FAILED(hr)) {
errmsg.Format(ResStr(IDS_MAINFRM_51), 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); // huh?
delete [] *ppData;
*ppData = NULL;
}
return false;
}
return true;
}
#include "jpeg.h"
#include "../../thirdparty/pngdib/pngdib.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) * DWORD(sizeof(bi->bmiColors[0]));
}
}
fwrite(&bfh, 1, sizeof(bfh), f);
fwrite(pData, 1, size, f);
fclose(f);
} else {
AfxMessageBox(ResStr(IDS_MAINFRM_53), MB_OK);
}
} else if(ext == _T(".png")) {
DWORD bmpsize = size;
LPBITMAPINFOHEADER pdib;
LPBITMAPFILEHEADER pbmfh;
void *pbits;
PNGDIB *pngdib;
int ret;
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) * DWORD(sizeof(bi->bmiColors[0]));
}
}
pbmfh = (LPBITMAPFILEHEADER)&bfh;
pbits = &pData[pbmfh->bfOffBits-sizeof(bfh)];
pdib = (LPBITMAPINFOHEADER)pData;
pngdib = pngdib_d2p_init();
pngdib_d2p_set_dib(pngdib,pdib,bmpsize,pbits,0);
pngdib_d2p_set_png_filename(pngdib, fn);
pngdib_d2p_set_gamma_label(pngdib, 1, PNGDIB_DEFAULT_FILE_GAMMA);
ret = pngdib_d2p_run(pngdib);
pngdib_done(pngdib);
if(ret) {
CString err_str;
err_str.Format(_T("%s\n%s (%d)"), IDS_MAINFRM_53, pngdib_get_error_msg(pngdib), ret);
AfxMessageBox(err_str, 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 || GetPlaybackMode() != PM_FILE /*&& GetPlaybackMode() != PM_DVD*/) {
return;
}
REFERENCE_TIME rtPos = GetPos();
REFERENCE_TIME rtDur = GetDur();
if(rtDur <= 0) {
AfxMessageBox(ResStr(IDS_MAINFRM_54));
return;
}
pMC->Pause();
GetMediaState(); // wait for completion of the pause command
//
CSize video, wh(0, 0), arxy(0, 0);
if (m_pMFVDC) {
m_pMFVDC->GetNativeVideoSize(&wh, &arxy);
} else 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 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(ResStr(IDS_MAINFRM_55));
return;
}
// with the overlay mixer IBasicVideo2 won't tell the new AR when changed dynamically
DVD_VideoAttributes VATR;
if(GetPlaybackMode() == 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 = max (1, min (10, s.iThumbCols)), rows = max(1, min (20, s.iThumbRows));
int margin = 5;
int infoheight = 70;
int width = max (256, min (2560, s.iThumbWidth));
int height = width * video.cy / video.cx * rows / cols + infoheight;
int dibsize = sizeof(BITMAPINFOHEADER) + width*height*4;
CAutoVectorPtr dib;
if(!dib.Allocate(dibsize)) {
AfxMessageBox(ResStr(IDS_MAINFRM_56));
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.vidrect = CRect(0, 0, width, height);
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 = DNew 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(ResStr(IDS_MAINFRM_57), 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 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 + (int)yi*sp);
DWORD* s1 = (DWORD*)(src + (int)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 = DNew 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.GetCurFileName());
path.StripPath();
CStringW fn = (LPCTSTR)path;
CStringW fs;
WIN32_FIND_DATA wfd;
HANDLE hFind = FindFirstFile(m_wndPlaylistBar.GetCurFileName(), &wfd);
if(hFind != INVALID_HANDLE_VALUE) {
FindClose(hFind);
__int64 size = (__int64(wfd.nFileSizeHigh)<<32)|wfd.nFileSizeLow;
const int MAX_FILE_SIZE_BUFFER = 65;
WCHAR szFileSize[MAX_FILE_SIZE_BUFFER];
StrFormatByteSizeW(size, szFileSize, sizeof(szFileSize));
fs.Format(ResStr(IDS_MAINFRM_58), szFileSize, 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(ResStr(IDS_MAINFRM_59),
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().strSnapShotExt);
return fn;
}
BOOL CMainFrame::IsRendererCompatibleWithSaveImage()
{
BOOL result = TRUE;
AppSettings& s = AfxGetAppSettings();
if(m_fRealMediaGraph) {
if(s.iRMVideoRendererType == VIDRNDT_RM_DEFAULT) {
AfxMessageBox(_T("The 'Save Image' and 'Save Thumbnails' functions do not work with the default video renderer for RealMedia.\nSelect one of the DirectX renderers for RealMedia in MPC's output options and reopen the file."));
result = FALSE;
}
} else {
if(m_fQuicktimeGraph) {
if(s.iQTVideoRendererType == VIDRNDT_QT_DEFAULT) {
AfxMessageBox(_T("The 'Save Image and 'Save Thumbnails' functions do not work with the default video renderer for QuickTime.\nSelect one of the DirectX renderers for QuickTime in MPC's output options and reopen the file."));
result = FALSE;
}
} else {
if(m_fShockwaveGraph) {
AfxMessageBox(_T("The 'Save Image' and 'Save Thumbnails' functions do not work for Shockwave files."));
result = FALSE;
} else {
if(s.iDSVideoRendererType == VIDRNDT_DS_OVERLAYMIXER) {
AfxMessageBox(_T("The 'Save Image' and 'Save Thumbnails' functions do not work with the Overlay Mixer video renderer.\nChange the video renderer in MPC's output options and reopen the file."));
result = FALSE;
}
}
}
}
return result;
}
CString CMainFrame::GetVidPos()
{
CString posstr = _T("");
if((GetPlaybackMode() == PM_FILE) || (GetPlaybackMode() == PM_DVD)) {
__int64 start, stop, pos;
m_wndSeekBar.GetRange(start, stop);
pos = m_wndSeekBar.GetPosReal();
DVD_HMSF_TIMECODE tcNow = RT2HMSF(pos);
DVD_HMSF_TIMECODE tcDur = RT2HMSF(stop);
if(tcDur.bHours > 0 || (pos >= stop && tcNow.bHours > 0)) {
posstr.Format(_T("%02d.%02d.%02d"), tcNow.bHours, tcNow.bMinutes, tcNow.bSeconds);
} else {
posstr.Format(_T("%02d.%02d"), tcNow.bMinutes, tcNow.bSeconds);
}
}
return posstr;
}
void CMainFrame::OnFileSaveImage()
{
AppSettings& s = AfxGetAppSettings();
/* Check if a compatible renderer is being used */
if(!IsRendererCompatibleWithSaveImage()) {
return;
}
CPath psrc(s.strSnapShotPath);
CStringW prefix = _T("snapshot");
if(GetPlaybackMode() == PM_FILE) {
CPath path(m_wndPlaylistBar.GetCurFileName());
path.StripPath();
prefix.Format(_T("%s_snapshot_%s"), path, GetVidPos());
} else if(GetPlaybackMode() == PM_DVD) {
prefix.Format(_T("snapshot_dvd_%s"), GetVidPos());
}
psrc.Combine(s.strSnapShotPath, MakeSnapshotFileName(prefix));
CFileDialog fd(FALSE, 0, (LPCTSTR)psrc,
OFN_EXPLORER|OFN_ENABLESIZING|OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_PATHMUSTEXIST|OFN_NOCHANGEDIR,
_T("BMP - Windows Bitmap (*.bmp)|*.bmp|JPG - JPEG Image (*.jpg)|*.jpg|PNG - Portable Network Graphics (*.png)|*.png||"), GetModalParent(), 0);
if(s.strSnapShotExt == _T(".bmp")) {
fd.m_pOFN->nFilterIndex = 1;
} else if(s.strSnapShotExt == _T(".jpg")) {
fd.m_pOFN->nFilterIndex = 2;
} else if(s.strSnapShotExt == _T(".png")) {
fd.m_pOFN->nFilterIndex = 3;
}
if(fd.DoModal() != IDOK) {
return;
}
if(fd.m_pOFN->nFilterIndex == 1) {
s.strSnapShotExt = _T(".bmp");
} else if(fd.m_pOFN->nFilterIndex == 2) {
s.strSnapShotExt = _T(".jpg");
} else {
fd.m_pOFN->nFilterIndex = 3;
s.strSnapShotExt = _T(".png");
}
CPath pdst(fd.GetPathName());
if(pdst.GetExtension().MakeLower() != s.strSnapShotExt) {
pdst.RenameExtension(s.strSnapShotExt);
}
CString path = (LPCTSTR)pdst;
pdst.RemoveFileSpec();
s.strSnapShotPath = (LPCTSTR)pdst;
SaveImage(path);
}
void CMainFrame::OnFileSaveImageAuto()
{
AppSettings& s = AfxGetAppSettings();
/* Check if a compatible renderer is being used */
if(!IsRendererCompatibleWithSaveImage()) {
return;
}
CStringW prefix = _T("snapshot");
if(GetPlaybackMode() == PM_FILE) {
CPath path(m_wndPlaylistBar.GetCurFileName());
path.StripPath();
prefix.Format(_T("%s_snapshot_%s"), path, GetVidPos());
} else if(GetPlaybackMode() == PM_DVD) {
prefix.Format(_T("snapshot_dvd_%s"), GetVidPos());
}
CString fn;
fn.Format(_T("%s\\%s"), s.strSnapShotPath, MakeSnapshotFileName(prefix));
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();
/* Check if a compatible renderer is being used */
if(!IsRendererCompatibleWithSaveImage()) {
return;
}
CPath psrc(s.strSnapShotPath);
CStringW prefix = _T("thumbs");
if(GetPlaybackMode() == PM_FILE) {
CPath path(m_wndPlaylistBar.GetCurFileName());
path.StripPath();
prefix.Format(_T("%s_thumbs"), path);
}
psrc.Combine(s.strSnapShotPath, MakeSnapshotFileName(prefix));
CSaveThumbnailsDialog fd(
s.iThumbRows, s.iThumbCols, s.iThumbWidth,
0, (LPCTSTR)psrc,
_T("BMP - Windows Bitmap (*.bmp)|*.bmp|JPG - JPEG Image (*.jpg)|*.jpg|PNG - Portable Network Graphics (*.png)|*.png||"), GetModalParent());
if(s.strSnapShotExt == _T(".bmp")) {
fd.m_pOFN->nFilterIndex = 1;
} else if(s.strSnapShotExt == _T(".jpg")) {
fd.m_pOFN->nFilterIndex = 2;
} else if(s.strSnapShotExt == _T(".png")) {
fd.m_pOFN->nFilterIndex = 3;
}
if(fd.DoModal() != IDOK) {
return;
}
if(fd.m_pOFN->nFilterIndex == 1) {
s.strSnapShotExt = _T(".bmp");
} else if(fd.m_pOFN->nFilterIndex == 2) {
s.strSnapShotExt = _T(".jpg");
} else {
fd.m_pOFN->nFilterIndex = 3;
s.strSnapShotExt = _T(".png");
}
s.iThumbRows = fd.m_rows;
s.iThumbCols = fd.m_cols;
s.iThumbWidth = fd.m_width;
CPath pdst(fd.GetPathName());
if(pdst.GetExtension().MakeLower() != s.strSnapShotExt) {
pdst.RenameExtension(s.strSnapShotExt);
}
CString path = (LPCTSTR)pdst;
pdst.RemoveFileSpec();
s.strSnapShotPath = (LPCTSTR)pdst;
SaveThumbnails(path);
}
void CMainFrame::OnUpdateFileSaveThumbnails(CCmdUI* pCmdUI)
{
OAFilterState fs = GetMediaState();
UNUSED_ALWAYS(fs);
pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly && (GetPlaybackMode() == PM_FILE /*|| GetPlaybackMode() == PM_DVD*/));
}
void CMainFrame::OnFileConvert()
{
CConvertDlg().DoModal();
}
void CMainFrame::OnUpdateFileConvert(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
}
void CMainFrame::OnFileLoadsubtitle()
{
if(!m_pCAP) {
AfxMessageBox(ResStr(IDS_MAINFRM_60)+
ResStr(IDS_MAINFRM_61)+
ResStr(IDS_MAINFRM_62)+
ResStr(IDS_MAINFRM_63)+
ResStr(IDS_MAINFRM_64)
, MB_OK);
return;
}
static TCHAR BASED_CODE szFilter[] =
_T(".srt .sub .ssa .ass .smi .psb .txt .idx .usf .xss|")
_T("*.srt;*.sub;*.ssa;*.ass;*smi;*.psb;*.txt;*.idx;*.usf;*.xss||");
CFileDialog fd(TRUE, NULL, NULL,
OFN_EXPLORER | OFN_ENABLESIZING | OFN_HIDEREADONLY|OFN_NOCHANGEDIR,
szFilter, GetModalParent(), 0);
if(fd.DoModal() != IDOK) {
return;
}
ISubStream *pSubStream = NULL;
if(LoadSubtitle(fd.GetPathName(), &pSubStream)) {
SetSubtitle(pSubStream); // the subtitle at the insert position according to LoadSubtitle()
}
}
void CMainFrame::OnUpdateFileLoadsubtitle(CCmdUI *pCmdUI)
{
pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && /*m_pCAP &&*/ !m_fAudioOnly);
}
void CMainFrame::OnFileSavesubtitle()
{
int i = m_iSubtitleSel;
POSITION pos = m_pSubStreams.GetHeadPosition();
while(pos && i >= 0) {
CComPtr pSubStream = m_pSubStreams.GetNext(pos);
if(i < pSubStream->GetStreamCount()) {
CLSID clsid;
if(FAILED(pSubStream->GetClassID(&clsid))) {
continue;
}
OpenMediaData *pOMD = m_wndPlaylistBar.GetCurOMD();
CString suggestedFileName("");
if(OpenFileData* p = dynamic_cast(pOMD)) {
// HACK: get the file name from the current playlist item
suggestedFileName = m_wndPlaylistBar.GetCurFileName();
suggestedFileName = suggestedFileName.Left(suggestedFileName.ReverseFind('.')); // exclude the extension, it will be auto completed
}
if(clsid == __uuidof(CVobSubFile)) {
CVobSubFile* pVSF = (CVobSubFile*)(ISubStream*)pSubStream;
// remember to set lpszDefExt to the first extension in the filter so that the save dialog autocompletes the extension
// and tracks attempts to overwrite in a graceful manner
CFileDialog fd(FALSE, _T("idx"), suggestedFileName,
OFN_EXPLORER|OFN_ENABLESIZING|OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_PATHMUSTEXIST|OFN_NOCHANGEDIR,
_T("VobSub (*.idx, *.sub)|*.idx;*.sub||"), GetModalParent(), 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;
// WATCH the order in GFN.h for exttype
filter += _T("SubRip (*.srt)|*.srt|");
filter += _T("MicroDVD (*.sub)|*.sub|");
filter += _T("SAMI (*.smi)|*.smi|");
filter += _T("PowerDivX (*.psb)|*.psb|");
filter += _T("SubStation Alpha (*.ssa)|*.ssa|");
filter += _T("Advanced SubStation Alpha (*.ass)|*.ass|");
filter += _T("|");
// same thing as in the case of CVobSubFile above for lpszDefExt
CSaveTextFileDialog fd(pRTS->m_encoding, _T("srt"), suggestedFileName, filter, GetModalParent());
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().strISDb + "/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().strISDb + "/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()
{
AppSettings& s = AfxGetAppSettings();
filehash fh;
if(!::hash((CString)m_wndPlaylistBar.GetCurFileName(), fh)) {
MessageBeep((UINT)-1);
return;
}
// TODO: put this on a worker thread
CStringA url = "http://" + s.strISDb + "/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)) {
AfxMessageBox(_T("Cannot connect to subtitle database site"), MB_OK);
return;
}
CStringA ticket;
CList movies;
isdb_movie m;
isdb_subtitle sub;
CAtlList 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") {
sub.reset();
sub.id = atoi(value);
} else if(param == "name") {
sub.name = value;
} else if(param == "discs") {
sub.discs = atoi(value);
} else if(param == "disc_no") {
sub.disc_no = atoi(value);
} else if(param == "format") {
sub.format = value;
} else if(param == "iso639_2") {
sub.iso639_2 = value;
} else if(param == "language") {
sub.language = value;
} else if(param == "nick") {
sub.nick = value;
} else if(param == "email") {
sub.email = value;
} else if(param == "" && value == "endsubtitle") {
m.subs.AddTail(sub);
} else if(param == "" && value == "endmovie") {
movies.AddTail(m);
} else if(param == "" && value == "end") {
break;
}
}
CSubtitleDlDlg dlg(movies, GetModalParent());
if(IDOK == dlg.DoModal()) {
if(dlg.m_fReplaceSubs) {
m_pSubStreams.RemoveAll();
}
CComPtr pSubStreamToSet;
POSITION pos = dlg.m_selsubs.GetHeadPosition();
while(pos) {
isdb_subtitle& sub = dlg.m_selsubs.GetNext(pos);
CStringA url = "http://" + s.strISDb + "/dl.php?";
CStringA args;
args.Format("id=%d&ticket=%s", sub.id, UrlEncode(ticket));
if(OpenUrl(is, CString(url+args), str)) {
CAutoPtr pRTS(DNew CRenderedTextSubtitle(&m_csSubLock, &s.subdefstyle, s.fUseDefaultSubtitlesStyle));
if(pRTS && pRTS->Open((BYTE*)(LPCSTR)str, str.GetLength(), DEFAULT_CHARSET, CString(sub.name)) && pRTS->GetStreamCount() > 0) {
CComPtr pSubStream = pRTS.Detach();
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.GetCurFileName(), this, GetModalParent());
m_fileinfo.DoModal();
}
void CMainFrame::OnUpdateFileProperties(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && GetPlaybackMode() == PM_FILE);
}
void CMainFrame::OnFileCloseMedia()
{
CloseMedia();
}
void CMainFrame::OnUpdateViewTearingTest(CCmdUI* pCmdUI)
{
pCmdUI->Enable (TRUE);
pCmdUI->SetCheck (AfxGetMyApp()->m_Renderers.m_fTearingTest);
}
void CMainFrame::OnViewTearingTest()
{
AfxGetMyApp()->m_Renderers.m_fTearingTest = ! AfxGetMyApp()->m_Renderers.m_fTearingTest;
}
void CMainFrame::OnUpdateViewDisplayStats(CCmdUI* pCmdUI)
{
AppSettings& s = AfxGetAppSettings();
CRenderersSettings& r = s.m_RenderersSettings;
bool supported = (s.iDSVideoRendererType == VIDRNDT_DS_EVR_CUSTOM ||
s.iDSVideoRendererType == VIDRNDT_DS_VMR9RENDERLESS ||
s.iDSVideoRendererType == VIDRNDT_DS_SYNC) &&
r.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE3D;
pCmdUI->Enable (supported);
pCmdUI->SetCheck (supported && (AfxGetMyApp()->m_Renderers.m_fDisplayStats));
}
void CMainFrame::OnViewResetStats()
{
AfxGetMyApp()->m_Renderers.m_bResetStats = true; // Reset by "consumer"
}
void CMainFrame::OnViewDisplayStatsSC()
{
++AfxGetMyApp()->m_Renderers.m_fDisplayStats;
if (AfxGetMyApp()->m_Renderers.m_fDisplayStats > 3) {
AfxGetMyApp()->m_Renderers.m_fDisplayStats = 0;
}
}
void CMainFrame::OnUpdateViewVSync(CCmdUI* pCmdUI)
{
AppSettings& s = AfxGetAppSettings();
CRenderersSettings& r = s.m_RenderersSettings;
bool supported = ((s.iDSVideoRendererType == VIDRNDT_DS_EVR_CUSTOM ||
s.iDSVideoRendererType == VIDRNDT_DS_VMR9RENDERLESS) &&
r.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE3D);
pCmdUI->Enable (supported);
pCmdUI->SetCheck (!supported || (r.m_RenderSettings.iVMR9VSync));
}
void CMainFrame::OnUpdateViewVSyncOffset(CCmdUI* pCmdUI)
{
AppSettings& s = AfxGetAppSettings();
CRenderersSettings& r = s.m_RenderersSettings;
bool supported = ((s.iDSVideoRendererType == VIDRNDT_DS_EVR_CUSTOM ||
s.iDSVideoRendererType == VIDRNDT_DS_VMR9RENDERLESS) &&
r.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE3D) &&
r.m_RenderSettings.fVMR9AlterativeVSync;
pCmdUI->Enable(supported);
CString Temp;
Temp.Format(L"%d", r.m_RenderSettings.iVMR9VSyncOffset);
pCmdUI->SetText(Temp);
}
void CMainFrame::OnUpdateViewVSyncAccurate(CCmdUI* pCmdUI)
{
AppSettings& s = AfxGetAppSettings();
CRenderersSettings& r = s.m_RenderersSettings;
bool supported = ((s.iDSVideoRendererType == VIDRNDT_DS_EVR_CUSTOM ||
s.iDSVideoRendererType == VIDRNDT_DS_VMR9RENDERLESS) &&
r.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE3D);
pCmdUI->Enable (supported);
pCmdUI->SetCheck(r.m_RenderSettings.iVMR9VSyncAccurate);
}
void CMainFrame::OnUpdateViewSynchronizeVideo(CCmdUI* pCmdUI)
{
AppSettings& s = AfxGetAppSettings();
CRenderersSettings& r = s.m_RenderersSettings;
bool supported = ((s.iDSVideoRendererType == VIDRNDT_DS_SYNC) && GetPlaybackMode() == PM_NONE);
pCmdUI->Enable(supported);
pCmdUI->SetCheck(r.m_RenderSettings.bSynchronizeVideo);
}
void CMainFrame::OnUpdateViewSynchronizeDisplay(CCmdUI* pCmdUI)
{
AppSettings& s = AfxGetAppSettings();
CRenderersSettings& r = s.m_RenderersSettings;
bool supported = ((s.iDSVideoRendererType == VIDRNDT_DS_SYNC) && GetPlaybackMode() == PM_NONE);
pCmdUI->Enable(supported);
pCmdUI->SetCheck(r.m_RenderSettings.bSynchronizeDisplay);
}
void CMainFrame::OnUpdateViewSynchronizeNearest(CCmdUI* pCmdUI)
{
AppSettings& s = AfxGetAppSettings();
CRenderersSettings& r = s.m_RenderersSettings;
bool supported = (s.iDSVideoRendererType == VIDRNDT_DS_SYNC);
pCmdUI->Enable(supported);
pCmdUI->SetCheck(r.m_RenderSettings.bSynchronizeNearest);
}
void CMainFrame::OnUpdateViewColorManagementEnable(CCmdUI* pCmdUI)
{
AppSettings& s = AfxGetAppSettings();
CRenderersSettings& r = s.m_RenderersSettings;
CRenderersData& rd = AfxGetMyApp()->m_Renderers;
bool supported = ((s.iDSVideoRendererType == VIDRNDT_DS_EVR_CUSTOM ||
s.iDSVideoRendererType == VIDRNDT_DS_VMR9RENDERLESS) &&
r.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE3D) &&
rd.m_bFP16Support;
pCmdUI->Enable (supported);
pCmdUI->SetCheck(r.m_RenderSettings.iVMR9ColorManagementEnable);
}
void CMainFrame::OnUpdateViewColorManagementInput(CCmdUI* pCmdUI)
{
AppSettings& s = AfxGetAppSettings();
CRenderersSettings& r = s.m_RenderersSettings;
CRenderersData& rd = AfxGetMyApp()->m_Renderers;
bool supported = ((s.iDSVideoRendererType == VIDRNDT_DS_EVR_CUSTOM ||
s.iDSVideoRendererType == VIDRNDT_DS_VMR9RENDERLESS) &&
r.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE3D) &&
rd.m_bFP16Support &&
r.m_RenderSettings.iVMR9ColorManagementEnable;
pCmdUI->Enable (supported);
switch (pCmdUI->m_nID) {
case ID_VIEW_COLORMANAGEMENT_INPUT_AUTO:
pCmdUI->SetCheck(r.m_RenderSettings.iVMR9ColorManagementInput == VIDEO_SYSTEM_UNKNOWN);
break;
case ID_VIEW_COLORMANAGEMENT_INPUT_HDTV:
pCmdUI->SetCheck(r.m_RenderSettings.iVMR9ColorManagementInput == VIDEO_SYSTEM_HDTV);
break;
case ID_VIEW_COLORMANAGEMENT_INPUT_SDTV_NTSC:
pCmdUI->SetCheck(r.m_RenderSettings.iVMR9ColorManagementInput == VIDEO_SYSTEM_SDTV_NTSC);
break;
case ID_VIEW_COLORMANAGEMENT_INPUT_SDTV_PAL:
pCmdUI->SetCheck(r.m_RenderSettings.iVMR9ColorManagementInput == VIDEO_SYSTEM_SDTV_PAL);
break;
}
}
void CMainFrame::OnUpdateViewColorManagementAmbientLight(CCmdUI* pCmdUI)
{
AppSettings& s = AfxGetAppSettings();
CRenderersSettings& r = s.m_RenderersSettings;
CRenderersData& rd = AfxGetMyApp()->m_Renderers;
bool supported = ((s.iDSVideoRendererType == VIDRNDT_DS_EVR_CUSTOM ||
s.iDSVideoRendererType == VIDRNDT_DS_VMR9RENDERLESS) &&
r.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE3D) &&
rd.m_bFP16Support &&
r.m_RenderSettings.iVMR9ColorManagementEnable;
pCmdUI->Enable (supported);
switch (pCmdUI->m_nID) {
case ID_VIEW_COLORMANAGEMENT_AMBIENTLIGHT_BRIGHT:
pCmdUI->SetCheck(r.m_RenderSettings.iVMR9ColorManagementAmbientLight == AMBIENT_LIGHT_BRIGHT);
break;
case ID_VIEW_COLORMANAGEMENT_AMBIENTLIGHT_DIM:
pCmdUI->SetCheck(r.m_RenderSettings.iVMR9ColorManagementAmbientLight == AMBIENT_LIGHT_DIM);
break;
case ID_VIEW_COLORMANAGEMENT_AMBIENTLIGHT_DARK:
pCmdUI->SetCheck(r.m_RenderSettings.iVMR9ColorManagementAmbientLight == AMBIENT_LIGHT_DARK);
break;
}
}
void CMainFrame::OnUpdateViewColorManagementIntent(CCmdUI* pCmdUI)
{
AppSettings& s = AfxGetAppSettings();
CRenderersSettings& r = s.m_RenderersSettings;
CRenderersData& rd = AfxGetMyApp()->m_Renderers;
bool supported = ((s.iDSVideoRendererType == VIDRNDT_DS_EVR_CUSTOM ||
s.iDSVideoRendererType == VIDRNDT_DS_VMR9RENDERLESS) &&
r.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE3D) &&
rd.m_bFP16Support &&
r.m_RenderSettings.iVMR9ColorManagementEnable;
pCmdUI->Enable (supported);
switch (pCmdUI->m_nID) {
case ID_VIEW_COLORMANAGEMENT_INTENT_PERCEPTUAL:
pCmdUI->SetCheck(r.m_RenderSettings.iVMR9ColorManagementIntent == COLOR_RENDERING_INTENT_PERCEPTUAL);
break;
case ID_VIEW_COLORMANAGEMENT_INTENT_RELATIVECOLORIMETRIC:
pCmdUI->SetCheck(r.m_RenderSettings.iVMR9ColorManagementIntent == COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC);
break;
case ID_VIEW_COLORMANAGEMENT_INTENT_SATURATION:
pCmdUI->SetCheck(r.m_RenderSettings.iVMR9ColorManagementIntent == COLOR_RENDERING_INTENT_SATURATION);
break;
case ID_VIEW_COLORMANAGEMENT_INTENT_ABSOLUTECOLORIMETRIC:
pCmdUI->SetCheck(r.m_RenderSettings.iVMR9ColorManagementIntent == COLOR_RENDERING_INTENT_ABSOLUTE_COLORIMETRIC);
break;
}
}
void CMainFrame::OnUpdateViewEVROutputRange(CCmdUI* pCmdUI)
{
AppSettings& s = AfxGetAppSettings();
CRenderersSettings& r = s.m_RenderersSettings;
bool supported = ((s.iDSVideoRendererType == VIDRNDT_DS_EVR_CUSTOM ||
s.iDSVideoRendererType == VIDRNDT_DS_SYNC) &&
r.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE3D);
pCmdUI->Enable (supported);
if (pCmdUI->m_nID == ID_VIEW_EVROUTPUTRANGE_0_255) {
pCmdUI->SetCheck(r.m_RenderSettings.iEVROutputRange == 0);
} else if (pCmdUI->m_nID == ID_VIEW_EVROUTPUTRANGE_16_235) {
pCmdUI->SetCheck(r.m_RenderSettings.iEVROutputRange == 1);
}
}
void CMainFrame::OnUpdateViewFlushGPU(CCmdUI* pCmdUI)
{
AppSettings& s = AfxGetAppSettings();
CRenderersSettings& r = s.m_RenderersSettings;
bool supported = ((s.iDSVideoRendererType == VIDRNDT_DS_EVR_CUSTOM ||
s.iDSVideoRendererType == VIDRNDT_DS_VMR9RENDERLESS) &&
r.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE3D);
pCmdUI->Enable (supported);
if (pCmdUI->m_nID == ID_VIEW_FLUSHGPU_BEFOREVSYNC) {
pCmdUI->SetCheck(r.m_RenderSettings.iVMRFlushGPUBeforeVSync != 0);
} else if (pCmdUI->m_nID == ID_VIEW_FLUSHGPU_AFTERPRESENT) {
pCmdUI->SetCheck(r.m_RenderSettings.iVMRFlushGPUAfterPresent != 0);
} else if (pCmdUI->m_nID == ID_VIEW_FLUSHGPU_WAIT) {
pCmdUI->SetCheck(r.m_RenderSettings.iVMRFlushGPUWait != 0);
}
}
void CMainFrame::OnUpdateViewD3DFullscreen(CCmdUI* pCmdUI)
{
AppSettings& s = AfxGetAppSettings();
CRenderersSettings& r = s.m_RenderersSettings;
bool supported = ((s.iDSVideoRendererType == VIDRNDT_DS_EVR_CUSTOM ||
s.iDSVideoRendererType == VIDRNDT_DS_VMR9RENDERLESS ||
s.iDSVideoRendererType == VIDRNDT_DS_SYNC) &&
r.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE3D);
pCmdUI->Enable (supported);
pCmdUI->SetCheck(s.fD3DFullscreen);
}
void CMainFrame::OnUpdateViewDisableDesktopComposition(CCmdUI* pCmdUI)
{
AppSettings& s = AfxGetAppSettings();
CRenderersSettings& r = s.m_RenderersSettings;
bool supported = ((s.iDSVideoRendererType == VIDRNDT_DS_EVR_CUSTOM ||
s.iDSVideoRendererType == VIDRNDT_DS_VMR9RENDERLESS ||
s.iDSVideoRendererType == VIDRNDT_DS_SYNC) &&
r.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE3D);
pCmdUI->Enable (supported);
pCmdUI->SetCheck(r.m_RenderSettings.iVMRDisableDesktopComposition);
}
void CMainFrame::OnUpdateViewAlternativeVSync(CCmdUI* pCmdUI)
{
AppSettings& s = AfxGetAppSettings();
CRenderersSettings& r = s.m_RenderersSettings;
bool supported = ((s.iDSVideoRendererType == VIDRNDT_DS_EVR_CUSTOM ||
s.iDSVideoRendererType == VIDRNDT_DS_VMR9RENDERLESS) &&
r.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE3D);
pCmdUI->Enable (supported);
pCmdUI->SetCheck(r.m_RenderSettings.fVMR9AlterativeVSync);
}
void CMainFrame::OnUpdateViewFullscreenGUISupport(CCmdUI* pCmdUI)
{
AppSettings& s = AfxGetAppSettings();
CRenderersSettings& r = s.m_RenderersSettings;
bool supported = ((s.iDSVideoRendererType == VIDRNDT_DS_EVR_CUSTOM ||
s.iDSVideoRendererType == VIDRNDT_DS_VMR9RENDERLESS) &&
r.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE3D);
pCmdUI->Enable (supported);
pCmdUI->SetCheck(r.m_RenderSettings.iVMR9FullscreenGUISupport);
}
void CMainFrame::OnUpdateViewHighColorResolution(CCmdUI* pCmdUI)
{
AppSettings& s = AfxGetAppSettings();
CRenderersSettings& r = s.m_RenderersSettings;
CRenderersData& rd = AfxGetMyApp()->m_Renderers;
bool supported = ((s.iDSVideoRendererType == VIDRNDT_DS_EVR_CUSTOM ||
s.iDSVideoRendererType == VIDRNDT_DS_SYNC) &&
r.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE3D) &&
rd.m_b10bitSupport;
pCmdUI->Enable (supported);
pCmdUI->SetCheck(r.m_RenderSettings.iEVRHighColorResolution);
}
void CMainFrame::OnUpdateViewForceInputHighColorResolution(CCmdUI* pCmdUI)
{
AppSettings& s = AfxGetAppSettings();
CRenderersSettings& r = s.m_RenderersSettings;
CRenderersData& rd = AfxGetMyApp()->m_Renderers;
bool supported = ((s.iDSVideoRendererType == VIDRNDT_DS_EVR_CUSTOM) &&
r.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE3D) &&
rd.m_b10bitSupport;
pCmdUI->Enable (supported);
pCmdUI->SetCheck(r.m_RenderSettings.iEVRForceInputHighColorResolution);
}
void CMainFrame::OnUpdateViewFullFloatingPointProcessing(CCmdUI* pCmdUI)
{
AppSettings& s = AfxGetAppSettings();
CRenderersSettings& r = s.m_RenderersSettings;
CRenderersData& rd = AfxGetMyApp()->m_Renderers;
bool supported = ((s.iDSVideoRendererType == VIDRNDT_DS_EVR_CUSTOM ||
s.iDSVideoRendererType == VIDRNDT_DS_VMR9RENDERLESS) &&
r.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE3D) &&
rd.m_bFP16Support;
pCmdUI->Enable (supported);
pCmdUI->SetCheck(r.m_RenderSettings.iVMR9FullFloatingPointProcessing);
}
void CMainFrame::OnUpdateViewHalfFloatingPointProcessing(CCmdUI* pCmdUI)
{
AppSettings& s = AfxGetAppSettings();
CRenderersSettings& r = s.m_RenderersSettings;
CRenderersData& rd = AfxGetMyApp()->m_Renderers;
bool supported = ((s.iDSVideoRendererType == VIDRNDT_DS_EVR_CUSTOM ||
s.iDSVideoRendererType == VIDRNDT_DS_VMR9RENDERLESS) &&
r.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE3D) &&
rd.m_bFP16Support;
pCmdUI->Enable (supported);
pCmdUI->SetCheck(r.m_RenderSettings.iVMR9HalfFloatingPointProcessing);
}
void CMainFrame::OnUpdateViewEnableFrameTimeCorrection(CCmdUI* pCmdUI)
{
AppSettings& s = AfxGetAppSettings();
CRenderersSettings& r = s.m_RenderersSettings;
bool supported = ((s.iDSVideoRendererType == VIDRNDT_DS_EVR_CUSTOM) &&
r.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE3D);
pCmdUI->Enable (supported);
pCmdUI->SetCheck(r.m_RenderSettings.iEVREnableFrameTimeCorrection);
}
void CMainFrame::OnUpdateViewVSyncOffsetIncrease(CCmdUI* pCmdUI)
{
AppSettings& s = AfxGetAppSettings();
CRenderersSettings& r = s.m_RenderersSettings;
bool supported = s.iDSVideoRendererType == VIDRNDT_DS_SYNC ||
(((s.iDSVideoRendererType == VIDRNDT_DS_EVR_CUSTOM ||
s.iDSVideoRendererType == VIDRNDT_DS_VMR9RENDERLESS) &&
r.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE3D) &&
r.m_RenderSettings.fVMR9AlterativeVSync);
pCmdUI->Enable (supported);
}
void CMainFrame::OnUpdateViewVSyncOffsetDecrease(CCmdUI* pCmdUI)
{
AppSettings& s = AfxGetAppSettings();
CRenderersSettings& r = s.m_RenderersSettings;
bool supported = s.iDSVideoRendererType == VIDRNDT_DS_SYNC ||
(((s.iDSVideoRendererType == VIDRNDT_DS_EVR_CUSTOM ||
s.iDSVideoRendererType == VIDRNDT_DS_VMR9RENDERLESS) &&
r.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE3D) &&
r.m_RenderSettings.fVMR9AlterativeVSync);
pCmdUI->Enable (supported);
}
void CMainFrame::OnViewVSync()
{
CRenderersSettings& s = AfxGetAppSettings().m_RenderersSettings;
s.m_RenderSettings.iVMR9VSync = !s.m_RenderSettings.iVMR9VSync;
s.UpdateData(true);
CString Format;
Format.Format(L"VSync: %s", s.m_RenderSettings.iVMR9VSync? L"On":L"Off");
m_OSD.DisplayMessage (OSD_TOPRIGHT, Format);
}
void CMainFrame::OnViewVSyncAccurate()
{
CRenderersSettings& s = AfxGetAppSettings().m_RenderersSettings;
s.m_RenderSettings.iVMR9VSyncAccurate = !s.m_RenderSettings.iVMR9VSyncAccurate;
s.UpdateData(true);
CString Format;
Format.Format(L"Accurate VSync: %s", s.m_RenderSettings.iVMR9VSyncAccurate? L"On":L"Off");
m_OSD.DisplayMessage (OSD_TOPRIGHT, Format);
}
void CMainFrame::OnViewSynchronizeVideo()
{
CRenderersSettings& s = AfxGetAppSettings().m_RenderersSettings;
s.m_RenderSettings.bSynchronizeVideo = !s.m_RenderSettings.bSynchronizeVideo;
if (s.m_RenderSettings.bSynchronizeVideo) {
s.m_RenderSettings.bSynchronizeDisplay = false;
s.m_RenderSettings.bSynchronizeNearest = false;
s.m_RenderSettings.iVMR9VSync = false;
s.m_RenderSettings.iVMR9VSyncAccurate = false;
s.m_RenderSettings.fVMR9AlterativeVSync = false;
}
s.UpdateData(true);
CString Format;
Format.Format(L"Synchronize Video to Display: %s", s.m_RenderSettings.bSynchronizeVideo? L"On":L"Off");
m_OSD.DisplayMessage (OSD_TOPRIGHT, Format);
}
void CMainFrame::OnViewSynchronizeDisplay()
{
CRenderersSettings& s = AfxGetAppSettings().m_RenderersSettings;
s.m_RenderSettings.bSynchronizeDisplay = !s.m_RenderSettings.bSynchronizeDisplay;
if (s.m_RenderSettings.bSynchronizeDisplay) {
s.m_RenderSettings.bSynchronizeVideo = false;
s.m_RenderSettings.bSynchronizeNearest = false;
s.m_RenderSettings.iVMR9VSync = false;
s.m_RenderSettings.iVMR9VSyncAccurate = false;
s.m_RenderSettings.fVMR9AlterativeVSync = false;
}
s.UpdateData(true);
CString Format;
Format.Format(L"Synchronize Display to Video: %s", s.m_RenderSettings.bSynchronizeDisplay? L"On":L"Off");
m_OSD.DisplayMessage (OSD_TOPRIGHT, Format);
}
void CMainFrame::OnViewSynchronizeNearest()
{
CRenderersSettings& s = AfxGetAppSettings().m_RenderersSettings;
s.m_RenderSettings.bSynchronizeNearest = !s.m_RenderSettings.bSynchronizeNearest;
if (s.m_RenderSettings.bSynchronizeNearest) {
s.m_RenderSettings.bSynchronizeVideo = false;
s.m_RenderSettings.bSynchronizeDisplay = false;
s.m_RenderSettings.iVMR9VSync = false;
s.m_RenderSettings.iVMR9VSyncAccurate = false;
s.m_RenderSettings.fVMR9AlterativeVSync = false;
}
s.UpdateData(true);
CString Format;
Format.Format(L"Present at Nearest VSync: %s", s.m_RenderSettings.bSynchronizeNearest? L"On":L"Off");
m_OSD.DisplayMessage (OSD_TOPRIGHT, Format);
}
void CMainFrame::OnViewColorManagementEnable()
{
CRenderersSettings& s = AfxGetAppSettings().m_RenderersSettings;
s.m_RenderSettings.iVMR9ColorManagementEnable = !s.m_RenderSettings.iVMR9ColorManagementEnable;
s.UpdateData(true);
CString Format;
Format.Format(L"Color Management: %s", s.m_RenderSettings.iVMR9ColorManagementEnable? L"On":L"Off");
m_OSD.DisplayMessage (OSD_TOPRIGHT, Format);
}
void CMainFrame::OnViewColorManagementInputAuto()
{
CRenderersSettings& s = AfxGetAppSettings().m_RenderersSettings;
s.m_RenderSettings.iVMR9ColorManagementInput = VIDEO_SYSTEM_UNKNOWN;
s.UpdateData(true);
CString Format;
Format.Format(L"Input Type: Auto-Detect");
m_OSD.DisplayMessage (OSD_TOPRIGHT, Format);
}
void CMainFrame::OnViewColorManagementInputHDTV()
{
CRenderersSettings& s = AfxGetAppSettings().m_RenderersSettings;
s.m_RenderSettings.iVMR9ColorManagementInput = VIDEO_SYSTEM_HDTV;
s.UpdateData(true);
CString Format;
Format.Format(L"Input Type: HDTV");
m_OSD.DisplayMessage (OSD_TOPRIGHT, Format);
}
void CMainFrame::OnViewColorManagementInputSDTV_NTSC()
{
CRenderersSettings& s = AfxGetAppSettings().m_RenderersSettings;
s.m_RenderSettings.iVMR9ColorManagementInput = VIDEO_SYSTEM_SDTV_NTSC;
s.UpdateData(true);
CString Format;
Format.Format(L"Input Type: SDTV NTSC");
m_OSD.DisplayMessage (OSD_TOPRIGHT, Format);
}
void CMainFrame::OnViewColorManagementInputSDTV_PAL()
{
CRenderersSettings& s = AfxGetAppSettings().m_RenderersSettings;
s.m_RenderSettings.iVMR9ColorManagementInput = VIDEO_SYSTEM_SDTV_PAL;
s.UpdateData(true);
CString Format;
Format.Format(L"Input Type: SDTV PAL");
m_OSD.DisplayMessage (OSD_TOPRIGHT, Format);
}
void CMainFrame::OnViewColorManagementAmbientLightBright()
{
CRenderersSettings& s = AfxGetAppSettings().m_RenderersSettings;
s.m_RenderSettings.iVMR9ColorManagementAmbientLight = AMBIENT_LIGHT_BRIGHT;
s.UpdateData(true);
CString Format;
Format.Format(L"Ambient Light: Bright (2.2 Gamma)");
m_OSD.DisplayMessage (OSD_TOPRIGHT, Format);
}
void CMainFrame::OnViewColorManagementAmbientLightDim()
{
CRenderersSettings& s = AfxGetAppSettings().m_RenderersSettings;
s.m_RenderSettings.iVMR9ColorManagementAmbientLight = AMBIENT_LIGHT_DIM;
s.UpdateData(true);
CString Format;
Format.Format(L"Ambient Light: Dim (2.35 Gamma)");
m_OSD.DisplayMessage (OSD_TOPRIGHT, Format);
}
void CMainFrame::OnViewColorManagementAmbientLightDark()
{
CRenderersSettings& s = AfxGetAppSettings().m_RenderersSettings;
s.m_RenderSettings.iVMR9ColorManagementAmbientLight = AMBIENT_LIGHT_DARK;
s.UpdateData(true);
CString Format;
Format.Format(L"Ambient Light: Dark (2.4 Gamma)");
m_OSD.DisplayMessage (OSD_TOPRIGHT, Format);
}
void CMainFrame::OnViewColorManagementIntentPerceptual()
{
CRenderersSettings& s = AfxGetAppSettings().m_RenderersSettings;
s.m_RenderSettings.iVMR9ColorManagementIntent = COLOR_RENDERING_INTENT_PERCEPTUAL;
s.UpdateData(true);
CString Format;
Format.Format(L"Rendering Intent: Perceptual");
m_OSD.DisplayMessage (OSD_TOPRIGHT, Format);
}
void CMainFrame::OnViewColorManagementIntentRelativeColorimetric()
{
CRenderersSettings& s = AfxGetAppSettings().m_RenderersSettings;
s.m_RenderSettings.iVMR9ColorManagementIntent = COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC;
s.UpdateData(true);
CString Format;
Format.Format(L"Rendering Intent: Relative Colorimetric");
m_OSD.DisplayMessage (OSD_TOPRIGHT, Format);
}
void CMainFrame::OnViewColorManagementIntentSaturation()
{
CRenderersSettings& s = AfxGetAppSettings().m_RenderersSettings;
s.m_RenderSettings.iVMR9ColorManagementIntent = COLOR_RENDERING_INTENT_SATURATION;
s.UpdateData(true);
CString Format;
Format.Format(L"Rendering Intent: Saturation");
m_OSD.DisplayMessage (OSD_TOPRIGHT, Format);
}
void CMainFrame::OnViewColorManagementIntentAbsoluteColorimetric()
{
CRenderersSettings& s = AfxGetAppSettings().m_RenderersSettings;
s.m_RenderSettings.iVMR9ColorManagementIntent = COLOR_RENDERING_INTENT_ABSOLUTE_COLORIMETRIC;
s.UpdateData(true);
CString Format;
Format.Format(L"Rendering Intent: Absolute Colorimetric");
m_OSD.DisplayMessage (OSD_TOPRIGHT, Format);
}
void CMainFrame::OnViewEVROutputRange_0_255()
{
CRenderersSettings& s = AfxGetAppSettings().m_RenderersSettings;
s.m_RenderSettings.iEVROutputRange = 0;
s.UpdateData(true);
CString Format;
Format.Format(L"Output Range: 0 - 255");
m_OSD.DisplayMessage (OSD_TOPRIGHT, Format);
}
void CMainFrame::OnViewEVROutputRange_16_235()
{
CRenderersSettings& s = AfxGetAppSettings().m_RenderersSettings;
s.m_RenderSettings.iEVROutputRange = 1;
s.UpdateData(true);
CString Format;
Format.Format(L"Output Range: 16 - 235");
m_OSD.DisplayMessage (OSD_TOPRIGHT, Format);
}
void CMainFrame::OnViewFlushGPUBeforeVSync()
{
CRenderersSettings& s = AfxGetAppSettings().m_RenderersSettings;
s.m_RenderSettings.iVMRFlushGPUBeforeVSync = !s.m_RenderSettings.iVMRFlushGPUBeforeVSync;
s.UpdateData(true);
CString Format;
Format.Format(L"Flush GPU before VSync: %s", s.m_RenderSettings.iVMRFlushGPUBeforeVSync? L"On":L"Off");
m_OSD.DisplayMessage (OSD_TOPRIGHT, Format);
}
void CMainFrame::OnViewFlushGPUAfterVSync()
{
CRenderersSettings& s = AfxGetAppSettings().m_RenderersSettings;
s.m_RenderSettings.iVMRFlushGPUAfterPresent = !s.m_RenderSettings.iVMRFlushGPUAfterPresent;
s.UpdateData(true);
CString Format;
Format.Format(L"Flush GPU after Present: %s", s.m_RenderSettings.iVMRFlushGPUAfterPresent? L"On":L"Off");
m_OSD.DisplayMessage (OSD_TOPRIGHT, Format);
}
void CMainFrame::OnViewFlushGPUWait()
{
CRenderersSettings& s = AfxGetAppSettings().m_RenderersSettings;
s.m_RenderSettings.iVMRFlushGPUWait = !s.m_RenderSettings.iVMRFlushGPUWait;
s.UpdateData(true);
CString Format;
Format.Format(L"Wait for GPU Flush: %s", s.m_RenderSettings.iVMRFlushGPUWait? L"On":L"Off");
m_OSD.DisplayMessage (OSD_TOPRIGHT, Format);
}
void CMainFrame::OnViewD3DFullScreen()
{
AppSettings& s = AfxGetAppSettings();
s.fD3DFullscreen = !s.fD3DFullscreen;
s.UpdateData(true);
CString Format;
Format.Format(L"D3D Fullscreen (Requires restart): %s", s.fD3DFullscreen? L"On":L"Off");
m_OSD.DisplayMessage (OSD_TOPRIGHT, Format);
}
void CMainFrame::OnViewDisableDesktopComposition()
{
CRenderersSettings& s = AfxGetAppSettings().m_RenderersSettings;
s.m_RenderSettings.iVMRDisableDesktopComposition = !s.m_RenderSettings.iVMRDisableDesktopComposition;
s.UpdateData(true);
CString Format;
Format.Format(L"Disable desktop composition: %s", s.m_RenderSettings.iVMRDisableDesktopComposition? L"On":L"Off");
m_OSD.DisplayMessage (OSD_TOPRIGHT, Format);
}
void CMainFrame::OnViewAlternativeVSync()
{
CRenderersSettings& s = AfxGetAppSettings().m_RenderersSettings;
s.m_RenderSettings.fVMR9AlterativeVSync = !s.m_RenderSettings.fVMR9AlterativeVSync;
s.UpdateData(true);
CString Format;
Format.Format(L"Alternative VSync: %s", s.m_RenderSettings.fVMR9AlterativeVSync? L"On":L"Off");
m_OSD.DisplayMessage (OSD_TOPRIGHT, Format);
}
void CMainFrame::OnViewResetDefault()
{
CRenderersSettings& s = AfxGetAppSettings().m_RenderersSettings;
s.m_RenderSettings.SetDefault();
s.UpdateData(true);
CString Format;
Format.Format(L"Renderer settings reset to default");
m_OSD.DisplayMessage (OSD_TOPRIGHT, Format);
}
void CMainFrame::OnViewResetOptimal()
{
CRenderersSettings& s = AfxGetAppSettings().m_RenderersSettings;
s.m_RenderSettings.SetOptimal();
s.UpdateData(true);
CString Format;
Format.Format(L"Renderer settings reset to optimal");
m_OSD.DisplayMessage (OSD_TOPRIGHT, Format);
}
void CMainFrame::OnViewFullscreenGUISupport()
{
CRenderersSettings& s = AfxGetAppSettings().m_RenderersSettings;
s.m_RenderSettings.iVMR9FullscreenGUISupport = !s.m_RenderSettings.iVMR9FullscreenGUISupport;
s.UpdateData(true);
CString Format;
Format.Format(L"D3D Fullscreen GUI Support: %s", s.m_RenderSettings.iVMR9FullscreenGUISupport? L"On":L"Off");
m_OSD.DisplayMessage (OSD_TOPRIGHT, Format);
}
void CMainFrame::OnViewHighColorResolution()
{
CRenderersSettings& s = AfxGetAppSettings().m_RenderersSettings;
s.m_RenderSettings.iEVRHighColorResolution = !s.m_RenderSettings.iEVRHighColorResolution;
s.UpdateData(true);
CString Format;
Format.Format(L"10-bit RGB Output: %s", s.m_RenderSettings.iEVRHighColorResolution? L"On":L"Off");
m_OSD.DisplayMessage (OSD_TOPRIGHT, Format);
}
void CMainFrame::OnViewForceInputHighColorResolution()
{
CRenderersSettings& s = AfxGetAppSettings().m_RenderersSettings;
s.m_RenderSettings.iEVRForceInputHighColorResolution = !s.m_RenderSettings.iEVRForceInputHighColorResolution;
s.UpdateData(true);
CString Format;
Format.Format(L"Force 10-bit RGB Input: %s", s.m_RenderSettings.iEVRForceInputHighColorResolution? L"On":L"Off");
m_OSD.DisplayMessage (OSD_TOPRIGHT, Format);
}
void CMainFrame::OnViewFullFloatingPointProcessing()
{
CRenderersSettings& s = AfxGetAppSettings().m_RenderersSettings;
s.m_RenderSettings.iVMR9FullFloatingPointProcessing = !s.m_RenderSettings.iVMR9FullFloatingPointProcessing;
if(s.m_RenderSettings.iVMR9FullFloatingPointProcessing) s.m_RenderSettings.iVMR9HalfFloatingPointProcessing = false;
s.UpdateData(true);
CString Format;
Format.Format(L"Full Floating Point Processing: %s", s.m_RenderSettings.iVMR9FullFloatingPointProcessing? L"On":L"Off");
m_OSD.DisplayMessage (OSD_TOPRIGHT, Format);
}
void CMainFrame::OnViewHalfFloatingPointProcessing()
{
CRenderersSettings& s = AfxGetAppSettings().m_RenderersSettings;
s.m_RenderSettings.iVMR9HalfFloatingPointProcessing = !s.m_RenderSettings.iVMR9HalfFloatingPointProcessing;
if(s.m_RenderSettings.iVMR9HalfFloatingPointProcessing) s.m_RenderSettings.iVMR9FullFloatingPointProcessing = false;
s.UpdateData(true);
CString Format;
Format.Format(L"Half Floating Point Processing: %s", s.m_RenderSettings.iVMR9HalfFloatingPointProcessing? L"On":L"Off");
m_OSD.DisplayMessage (OSD_TOPRIGHT, Format);
}
void CMainFrame::OnViewEnableFrameTimeCorrection()
{
CRenderersSettings& s = AfxGetAppSettings().m_RenderersSettings;
s.m_RenderSettings.iEVREnableFrameTimeCorrection = !s.m_RenderSettings.iEVREnableFrameTimeCorrection;
s.UpdateData(true);
CString Format;
Format.Format(L"Frame Time Correction: %s", s.m_RenderSettings.iEVREnableFrameTimeCorrection? L"On":L"Off");
m_OSD.DisplayMessage (OSD_TOPRIGHT, Format);
}
void CMainFrame::OnViewVSyncOffsetIncrease()
{
AppSettings& s = AfxGetAppSettings();
CRenderersSettings& r = s.m_RenderersSettings;
CString Format;
if (s.iDSVideoRendererType == VIDRNDT_DS_SYNC) {
r.m_RenderSettings.fTargetSyncOffset = r.m_RenderSettings.fTargetSyncOffset - 0.5; // Yeah, it should be a "-"
Format.Format(L"Target VSync Offset: %.1f", r.m_RenderSettings.fTargetSyncOffset);
} else {
++r.m_RenderSettings.iVMR9VSyncOffset;
Format.Format(L"VSync Offset: %d", r.m_RenderSettings.iVMR9VSyncOffset);
}
r.UpdateData(true);
m_OSD.DisplayMessage(OSD_TOPRIGHT, Format);
}
void CMainFrame::OnViewVSyncOffsetDecrease()
{
AppSettings& s = AfxGetAppSettings();
CRenderersSettings& r = s.m_RenderersSettings;
CString Format;
if (s.iDSVideoRendererType == VIDRNDT_DS_SYNC) {
r.m_RenderSettings.fTargetSyncOffset = r.m_RenderSettings.fTargetSyncOffset + 0.5;
Format.Format(L"Target VSync Offset: %.1f", r.m_RenderSettings.fTargetSyncOffset);
} else {
--r.m_RenderSettings.iVMR9VSyncOffset;
Format.Format(L"VSync Offset: %d", r.m_RenderSettings.iVMR9VSyncOffset);
}
r.UpdateData(true);
m_OSD.DisplayMessage(OSD_TOPRIGHT, Format);
}
void CMainFrame::OnUpdateViewRemainingTime(CCmdUI* pCmdUI)
{
AppSettings& s = AfxGetAppSettings();
pCmdUI->Enable (s.fShowOSD && (m_iMediaLoadState != MLS_CLOSED));
pCmdUI->SetCheck (m_bRemainingTime);
}
void CMainFrame::OnViewRemainingTime()
{
m_bRemainingTime = !m_bRemainingTime;
if (!m_bRemainingTime) {
m_OSD.ClearMessage();
}
}
void CMainFrame::OnUpdateShaderToggle(CCmdUI* pCmdUI)
{
pCmdUI->Enable (TRUE);
pCmdUI->SetCheck (m_bToggleShader);
}
void CMainFrame::OnUpdateShaderToggleScreenSpace(CCmdUI* pCmdUI)
{
pCmdUI->Enable (TRUE);
pCmdUI->SetCheck (m_bToggleShaderScreenSpace);
}
void CMainFrame::OnShaderToggle()
{
m_bToggleShader = !m_bToggleShader;
if (!m_bToggleShader) {
SetShaders();
m_OSD.DisplayMessage (OSD_TOPRIGHT, ResStr(IDS_MAINFRM_65));
} else {
if (m_pCAP) {
m_pCAP->SetPixelShader(NULL, NULL);
}
m_OSD.DisplayMessage (OSD_TOPRIGHT, ResStr(IDS_MAINFRM_66));
}
}
void CMainFrame::OnShaderToggleScreenSpace()
{
m_bToggleShaderScreenSpace = !m_bToggleShaderScreenSpace;
if (!m_bToggleShaderScreenSpace) {
SetShaders();
m_OSD.DisplayMessage (OSD_TOPRIGHT, ResStr(IDS_MAINFRM_PPONSCR));
} else {
if (m_pCAP2) {
m_pCAP2->SetPixelShader2(NULL, NULL, true);
}
m_OSD.DisplayMessage (OSD_TOPRIGHT, ResStr(IDS_MAINFRM_PPOFFSCR));
}
}
void CMainFrame::OnD3DFullscreenToggle()
{
AppSettings& s = AfxGetAppSettings();
LPCTSTR strMsg;
s.fD3DFullscreen = !s.fD3DFullscreen;
strMsg = s.fD3DFullscreen ? ResStr(IDS_MAINFRM_67) : _T("D3D Fullscreen off");
if (m_iMediaLoadState == MLS_CLOSED) {
m_closingmsg = strMsg;
} else {
m_OSD.DisplayMessage (OSD_TOPRIGHT, strMsg);
}
}
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()
{
AppSettings& s = AfxGetAppSettings();
s.iCaptionMenuMode++;
s.iCaptionMenuMode %= MODE_COUNT; // three states: normal->borderless->frame only->
if ( m_fFullScreen ) {
return;
}
DWORD dwRemove = 0, dwAdd = 0;
HMENU hMenu = NULL;
CRect wr;
GetWindowRect( &wr );
switch(s.iCaptionMenuMode) {
case MODE_SHOWCAPTIONMENU: // borderless -> normal
dwAdd = WS_CAPTION | WS_THICKFRAME;
hMenu = m_hMenuDefault;
wr.right += GetSystemMetrics(SM_CXSIZEFRAME) * 2;
wr.bottom += GetSystemMetrics(SM_CYSIZEFRAME) * 2;
wr.bottom += GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYMENU);
break;
case MODE_HIDEMENU: // normal -> hidemenu
hMenu = NULL;
wr.bottom -= GetSystemMetrics(SM_CYMENU);
break;
case MODE_FRAMEONLY: // hidemenu -> frameonly
dwRemove = WS_CAPTION;
wr.bottom -= GetSystemMetrics(SM_CYCAPTION);
break;
case MODE_BORDERLESS: // frameonly -> borderless
dwRemove = WS_THICKFRAME;
wr.right -= GetSystemMetrics(SM_CXSIZEFRAME) * 2;
wr.bottom -= GetSystemMetrics(SM_CYSIZEFRAME) * 2;
break;
}
ModifyStyle(dwRemove, dwAdd, SWP_NOZORDER);
::SetMenu(m_hWnd, hMenu);
// NOTE: r.left and r.top are ignored due to SWP_NOMOVE flag
SetWindowPos(NULL, wr.left, wr.top, wr.Width(), wr.Height(), SWP_FRAMECHANGED|/*SWP_NOSIZE|*/SWP_NOMOVE|SWP_NOZORDER);
MoveVideoWindow();
}
void CMainFrame::OnUpdateViewCaptionmenu(CCmdUI* pCmdUI)
{
static int NEXT_MODE[] = {IDS_VIEW_HIDEMENU, IDS_VIEW_FRAMEONLY, IDS_VIEW_BORDERLESS, IDS_VIEW_CAPTIONMENU};
int idx = (AfxGetAppSettings().iCaptionMenuMode %= MODE_COUNT);
pCmdUI->SetText(ResStr(NEXT_MODE[idx]));
}
void CMainFrame::OnViewControlBar(UINT nID)
{
nID -= ID_VIEW_SEEKER;
ShowControls(AfxGetAppSettings().nCS ^ (1<m_nID - ID_VIEW_SEEKER;
pCmdUI->SetCheck(!!(AfxGetAppSettings().nCS & (1<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 /*&& (GetPlaybackMode() == PM_FILE || GetPlaybackMode() == PM_CAPTURE)*/);
}
void CMainFrame::OnViewEditListEditor()
{
AppSettings& s = AfxGetAppSettings();
if (s.fEnableEDLEditor || (AfxMessageBox(_T("Do you want to activate EDL editor?"), MB_YESNO) == IDYES)) {
s.fEnableEDLEditor = true;
ShowControlBar(&m_wndEditListEditor, !m_wndEditListEditor.IsWindowVisible(), TRUE);
}
}
void CMainFrame::OnEDLIn()
{
if(AfxGetAppSettings().fEnableEDLEditor && (m_iMediaLoadState == MLS_LOADED) && (GetPlaybackMode() == PM_FILE)) {
REFERENCE_TIME rt;
pMS->GetCurrentPosition(&rt);
m_wndEditListEditor.SetIn(rt);
}
}
void CMainFrame::OnUpdateEDLIn(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_wndEditListEditor.IsWindowVisible());
}
void CMainFrame::OnEDLOut()
{
if(AfxGetAppSettings().fEnableEDLEditor && (m_iMediaLoadState == MLS_LOADED) && (GetPlaybackMode() == PM_FILE)) {
REFERENCE_TIME rt;
pMS->GetCurrentPosition(&rt);
m_wndEditListEditor.SetOut(rt);
}
}
void CMainFrame::OnUpdateEDLOut(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_wndEditListEditor.IsWindowVisible());
}
void CMainFrame::OnEDLNewClip()
{
if(AfxGetAppSettings().fEnableEDLEditor && (m_iMediaLoadState == MLS_LOADED) && (GetPlaybackMode() == PM_FILE)) {
REFERENCE_TIME rt;
pMS->GetCurrentPosition(&rt);
m_wndEditListEditor.NewClip(rt);
}
}
void CMainFrame::OnUpdateEDLNewClip(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_wndEditListEditor.IsWindowVisible());
}
void CMainFrame::OnEDLSave()
{
if(AfxGetAppSettings().fEnableEDLEditor && (m_iMediaLoadState == MLS_LOADED) && (GetPlaybackMode() == PM_FILE)) {
m_wndEditListEditor.Save();
}
}
void CMainFrame::OnUpdateEDLSave(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_wndEditListEditor.IsWindowVisible());
}
// Navigation menu
void CMainFrame::OnViewNavigation()
{
AppSettings& s = AfxGetAppSettings();
s.fHideNavigation = !s.fHideNavigation;
m_wndNavigationBar.m_navdlg.UpdateElementList();
if (GetPlaybackMode() == PM_CAPTURE) {
ShowControlBar(&m_wndNavigationBar, !s.fHideNavigation, TRUE);
}
}
void CMainFrame::OnUpdateViewNavigation(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(!AfxGetAppSettings().fHideNavigation);
pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && GetPlaybackMode() == PM_CAPTURE && AfxGetAppSettings().iDefaultCaptureDevice == 1);
}
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 && GetPlaybackMode() == 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()
{
while(AfxGetAppSettings().iCaptionMenuMode!=MODE_BORDERLESS) {
SendMessage(WM_COMMAND, ID_VIEW_CAPTIONMENU);
}
ShowControls(CS_NONE);
}
void CMainFrame::OnUpdateViewMinimal(CCmdUI* pCmdUI)
{
}
void CMainFrame::OnViewCompact()
{
while(AfxGetAppSettings().iCaptionMenuMode!=MODE_FRAMEONLY) {
SendMessage(WM_COMMAND, ID_VIEW_CAPTIONMENU);
}
ShowControls(CS_TOOLBAR);
}
void CMainFrame::OnUpdateViewCompact(CCmdUI* pCmdUI)
{
}
void CMainFrame::OnViewNormal()
{
while(AfxGetAppSettings().iCaptionMenuMode!=MODE_SHOWCAPTIONMENU) {
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(true, 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(true, 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);
int dvs = pCmdUI->m_nID - ID_VIEW_VF_HALF;
pCmdUI->SetRadio(AfxGetAppSettings().iDefaultVideoSize == dvs);
}
void CMainFrame::OnViewSwitchVideoFrame()
{
int vs = AfxGetAppSettings().iDefaultVideoSize;
if (vs <= DVS_DOUBLE || vs == DVS_FROMOUTSIDE) {
vs = DVS_STRETCH;
} else if (vs == DVS_FROMINSIDE) {
vs = DVS_ZOOM1;
} else if (vs == DVS_ZOOM2) {
vs = DVS_FROMOUTSIDE;
} else {
vs++;
}
switch(vs) { // TODO: Read messages from resource file
case DVS_STRETCH:
m_OSD.DisplayMessage (OSD_TOPLEFT, ResStr(IDS_STRETCH_TO_WINDOW));
break;
case DVS_FROMINSIDE:
m_OSD.DisplayMessage (OSD_TOPLEFT, ResStr(IDS_TOUCH_WINDOW_FROM_INSIDE));
break;
case DVS_ZOOM1:
m_OSD.DisplayMessage (OSD_TOPLEFT, ResStr(IDS_ZOOM1));
break;
case DVS_ZOOM2:
m_OSD.DisplayMessage (OSD_TOPLEFT, ResStr(IDS_ZOOM2));
break;
case DVS_FROMOUTSIDE:
m_OSD.DisplayMessage (OSD_TOPLEFT, ResStr(IDS_TOUCH_WINDOW_FROM_OUTSIDE));
break;
}
AfxGetAppSettings().iDefaultVideoSize = vs;
m_ZoomX = m_ZoomY = 1;
m_PosX = m_PosY = 0.5;
MoveVideoWindow();
}
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((INT_PTR)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_s(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_AngleX -= 2;
break;
case ID_PANSCAN_ROTATEYP:
m_AngleY += 2;
break;
case ID_PANSCAN_ROTATEYM:
m_AngleY -= 2;
break;
case ID_PANSCAN_ROTATEZP:
m_AngleZ += 2;
break;
case ID_PANSCAN_ROTATEZM:
m_AngleZ -= 2;
break;
default:
return;
}
m_pCAP->SetVideoAngle(Vector(DegToRad(m_AngleX), DegToRad(m_AngleY), DegToRad(m_AngleZ)));
CString info;
info.Format(_T("x: %d, y: %d, z: %d"), m_AngleX, m_AngleY, m_AngleZ);
SendStatusMessage(info, 3000);
}
void CMainFrame::OnUpdateViewRotate(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly && m_pCAP);
}
// FIXME
const static SIZE s_ar[] = {{0,0}, {4,3}, {5,4}, {16,9}, {235,100}, {185,100}};
void CMainFrame::OnViewAspectRatio(UINT nID)
{
CSize& ar = AfxGetAppSettings().sizeAspectRatio;
ar = s_ar[nID - ID_ASPECTRATIO_START];
CString info;
if(ar.cx && ar.cy) {
info.Format(ResStr(IDS_MAINFRM_68), ar.cx, ar.cy);
} else {
info.Format(ResStr(IDS_MAINFRM_69));
}
SendStatusMessage(info, 3000);
m_OSD.DisplayMessage(OSD_TOPLEFT, info, 3000);
MoveVideoWindow();
}
void CMainFrame::OnUpdateViewAspectRatio(CCmdUI* pCmdUI)
{
pCmdUI->SetRadio(AfxGetAppSettings().sizeAspectRatio == s_ar[pCmdUI->m_nID - ID_ASPECTRATIO_START]);
pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly);
}
void CMainFrame::OnViewAspectRatioNext()
{
CSize& ar = AfxGetAppSettings().sizeAspectRatio;
UINT nID = ID_ASPECTRATIO_START;
for(int i = 0; i < countof(s_ar); i++) {
if(ar == s_ar[i]) {
nID += (i + 1) % countof(s_ar);
break;
}
}
OnViewAspectRatio(nID);
}
void CMainFrame::OnViewOntop(UINT nID)
{
nID -= ID_ONTOP_NEVER;
if(AfxGetAppSettings().iOnTop == (int)nID) {
nID = !nID;
}
SetAlwaysOnTop(nID);
}
void CMainFrame::OnUpdateViewOntop(CCmdUI* pCmdUI)
{
int onTop = pCmdUI->m_nID - ID_ONTOP_NEVER;
pCmdUI->SetRadio(AfxGetAppSettings().iOnTop == onTop);
}
void CMainFrame::OnViewOptions()
{
ShowOptions();
}
// play
void CMainFrame::OnPlayPlay()
{
if(m_iMediaLoadState == MLS_CLOSED) {
OpenCurPlaylistItem();
return;
}
if(m_iMediaLoadState == MLS_LOADED) {
if(GetMediaState() == State_Stopped) {
m_iSpeedLevel = 0;
}
if(GetPlaybackMode() == PM_FILE) {
m_iSpeedLevel = 0;
if(m_fEndOfStream) {
SendMessage(WM_COMMAND, ID_PLAY_STOP);
}
pMS->SetRate (1.0);
pMC->Run();
} else if(GetPlaybackMode() == PM_DVD) {
double dRate = 1.0;
m_iSpeedLevel = 0;
pDVDC->PlayForwards(dRate, DVD_CMD_FLAG_Block, NULL);
pDVDC->Pause(FALSE);
pMC->Run();
} else if(GetPlaybackMode() == PM_CAPTURE) {
pMC->Stop(); // audio preview won't be in sync if we run it from paused state
pMC->Run();
if (AfxGetAppSettings().iDefaultCaptureDevice == 1) {
CComQIPtr pTun = pGB;
if (pTun) {
pTun->SetChannel (AfxGetAppSettings().nDVBLastChannel);
DisplayCurrentChannelOSD();
}
}
}
SetTimersPlay();
if(m_fFrameSteppingActive) { // FIXME
m_fFrameSteppingActive = false;
pBA->put_Volume(m_VolumeBeforeFrameStepping);
}
SetAlwaysOnTop(AfxGetAppSettings().iOnTop);
}
MoveVideoWindow();
m_Lcd.SetStatusMessage(ResStr(IDS_CONTROLS_PLAYING), 3000);
SetPlayState (PS_PLAY);
m_OpenFile = false;
}
void CMainFrame::OnPlayPauseI()
{
if(m_iMediaLoadState == MLS_LOADED) {
//SetAlwaysOnTop(AfxGetAppSettings().iOnTop);
if(GetPlaybackMode() == PM_FILE) {
pMC->Pause();
} else if(GetPlaybackMode() == PM_DVD) {
pMC->Pause();
} else if(GetPlaybackMode() == PM_CAPTURE) {
pMC->Pause();
}
SetTimersPlay();
SetAlwaysOnTop(AfxGetAppSettings().iOnTop);
}
MoveVideoWindow();
m_Lcd.SetStatusMessage(ResStr(IDS_CONTROLS_PAUSED), 3000);
SetPlayState (PS_PAUSE);
}
void CMainFrame::OnPlayPause()
{
// Support ffdshow queuing.
// To avoid black out on pause, we have to lock g_ffdshowReceive to synchronize with ReceiveMine.
if(queue_ffdshow_support) {
CAutoLock lck(&g_ffdshowReceive);
return OnPlayPauseI();
}
OnPlayPauseI();
}
void CMainFrame::OnPlayPlaypause()
{
OAFilterState fs = GetMediaState();
if(fs == State_Running) {
SendMessage(WM_COMMAND, ID_PLAY_PAUSE);
} else if(fs == State_Stopped || fs == State_Paused) {
SendMessage(WM_COMMAND, ID_PLAY_PLAY);
}
}
void CMainFrame::OnPlayStop()
{
if(m_iMediaLoadState == MLS_LOADED) {
if(GetPlaybackMode() == PM_FILE) {
LONGLONG pos = 0;
pMS->SetPositions(&pos, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning);
pMC->Stop();
// BUG: after pause or stop the netshow url source filter won't continue
// on the next play command, unless we cheat it by setting the file name again.
//
// Note: WMPx may be using some undocumented interface to restart streaming.
BeginEnumFilters(pGB, pEF, pBF) {
CComQIPtr pAMNS = pBF;
CComQIPtr pFSF = pBF;
if(pAMNS && pFSF) {
WCHAR* pFN = NULL;
AM_MEDIA_TYPE mt;
if(SUCCEEDED(pFSF->GetCurFile(&pFN, &mt)) && pFN && *pFN) {
pFSF->Load(pFN, NULL);
CoTaskMemFree(pFN);
}
break;
}
}
EndEnumFilters;
} else if(GetPlaybackMode() == PM_DVD) {
pDVDC->SetOption(DVD_ResetOnStop, TRUE);
pMC->Stop();
pDVDC->SetOption(DVD_ResetOnStop, FALSE);
} else if(GetPlaybackMode() == PM_CAPTURE) {
pMC->Stop();
}
m_iSpeedLevel = 0;
if(m_fFrameSteppingActive) { // FIXME
m_fFrameSteppingActive = false;
pBA->put_Volume(m_VolumeBeforeFrameStepping);
}
m_fEndOfStream = false;
}
m_nLoops = 0;
if(m_hWnd) {
KillTimersStop();
MoveVideoWindow();
if(m_iMediaLoadState == MLS_LOADED) {
__int64 start, stop;
m_wndSeekBar.GetRange(start, stop);
GUID tf;
pMS->GetTimeFormat(&tf);
if (GetPlaybackMode() != PM_CAPTURE) {
m_wndStatusBar.SetStatusTimer(m_wndSeekBar.GetPosReal(), stop, !!m_wndSubresyncBar.IsWindowVisible(), &tf);
}
SetAlwaysOnTop(AfxGetAppSettings().iOnTop);
}
}
m_Lcd.SetStatusMessage(ResStr(IDS_CONTROLS_STOPPED), 3000);
SetPlayState (PS_STOP);
}
void CMainFrame::OnUpdatePlayPauseStop(CCmdUI* pCmdUI)
{
OAFilterState fs = m_fFrameSteppingActive ? State_Paused : GetMediaState();
pCmdUI->SetCheck(fs == State_Running && pCmdUI->m_nID == ID_PLAY_PLAY
|| fs == State_Paused && pCmdUI->m_nID == ID_PLAY_PAUSE
|| fs == State_Stopped && pCmdUI->m_nID == ID_PLAY_STOP
|| (fs == State_Paused || fs == State_Running) && pCmdUI->m_nID == ID_PLAY_PLAYPAUSE);
bool fEnable = false;
if(fs >= 0) {
if(GetPlaybackMode() == PM_FILE || GetPlaybackMode() == PM_CAPTURE) {
fEnable = true;
if(fs == State_Stopped && pCmdUI->m_nID == ID_PLAY_PAUSE && m_fRealMediaGraph) {
fEnable = false; // can't go into paused state from stopped with rm
} else if(m_fCapturing) {
fEnable = false;
} else if(m_fLiveWM && pCmdUI->m_nID == ID_PLAY_PAUSE) {
fEnable = false;
}
} else if(GetPlaybackMode() == PM_DVD) {
fEnable = m_iDVDDomain != DVD_DOMAIN_VideoManagerMenu
&& m_iDVDDomain != DVD_DOMAIN_VideoTitleSetMenu;
if(fs == State_Stopped && pCmdUI->m_nID == ID_PLAY_PAUSE) {
fEnable = false;
}
}
} else if (pCmdUI->m_nID == ID_PLAY_PLAY && m_wndPlaylistBar.GetCount() > 0) {
fEnable = true;
}
pCmdUI->Enable(fEnable);
}
void CMainFrame::OnPlayFramestep(UINT nID)
{
REFERENCE_TIME rt;
if(pFS && m_fQuicktimeGraph) {
if(GetMediaState() != State_Paused) {
SendMessage(WM_COMMAND, ID_PLAY_PAUSE);
}
pFS->Step(nID == ID_PLAY_FRAMESTEP ? 1 : -1, NULL);
} else if(pFS && nID == ID_PLAY_FRAMESTEP) {
if(GetMediaState() != State_Paused && !queue_ffdshow_support) {
SendMessage(WM_COMMAND, ID_PLAY_PAUSE);
}
// To support framestep back, store the initial position when
// stepping forward
if (m_nStepForwardCount == 0) {
pMS->GetCurrentPosition(&m_rtStepForwardStart);
}
m_fFrameSteppingActive = true;
m_VolumeBeforeFrameStepping = m_wndToolBar.Volume;
pBA->put_Volume(-10000);
pFS->Step(1, NULL);
} else if(S_OK == pMS->IsFormatSupported(&TIME_FORMAT_FRAME)) {
if(GetMediaState() != State_Paused) {
SendMessage(WM_COMMAND, ID_PLAY_PAUSE);
}
pMS->SetTimeFormat(&TIME_FORMAT_FRAME);
pMS->GetCurrentPosition(&rt);
if(nID == ID_PLAY_FRAMESTEP) {
rt++;
} else if(nID == ID_PLAY_FRAMESTEPCANCEL) {
rt--;
}
pMS->SetPositions(&rt, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning);
pMS->SetTimeFormat(&TIME_FORMAT_MEDIA_TIME);
} else { //if (s.iDSVideoRendererType != VIDRNDT_DS_VMR9WINDOWED && s.iDSVideoRendererType != VIDRNDT_DS_VMR9RENDERLESS)
if(GetMediaState() != State_Paused) {
SendMessage(WM_COMMAND, ID_PLAY_PAUSE);
}
REFERENCE_TIME rtAvgTime = 0;
BeginEnumFilters(pGB, pEF, pBF) {
BeginEnumPins(pBF, pEP, pPin) {
AM_MEDIA_TYPE mt;
pPin->ConnectionMediaType(&mt);
if(mt.majortype == MEDIATYPE_Video && mt.formattype == FORMAT_VideoInfo) {
rtAvgTime = ((VIDEOINFOHEADER*)mt.pbFormat)->AvgTimePerFrame;
} else if(mt.majortype == MEDIATYPE_Video && mt.formattype == FORMAT_VideoInfo2) {
rtAvgTime = ((VIDEOINFOHEADER2*)mt.pbFormat)->AvgTimePerFrame;
}
}
EndEnumPins;
}
EndEnumFilters;
// Exit of framestep forward : calculate the initial position
if (m_nStepForwardCount != 0) {
pFS->CancelStep();
rt = m_rtStepForwardStart + m_nStepForwardCount*rtAvgTime;
m_nStepForwardCount = 0;
} else {
pMS->GetCurrentPosition(&rt);
}
if(nID == ID_PLAY_FRAMESTEP) {
rt += rtAvgTime;
} else if(nID == ID_PLAY_FRAMESTEPCANCEL) {
rt -= rtAvgTime;
}
pMS->SetPositions(&rt, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning);
}
}
void CMainFrame::OnUpdatePlayFramestep(CCmdUI* pCmdUI)
{
bool fEnable = false;
if(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly &&
(GetPlaybackMode() != PM_DVD || m_iDVDDomain == DVD_DOMAIN_Title) &&
GetPlaybackMode() != PM_CAPTURE &&
!m_fLiveWM) {
if(S_OK == pMS->IsFormatSupported(&TIME_FORMAT_FRAME)) {
fEnable = true;
} else if(pCmdUI->m_nID == ID_PLAY_FRAMESTEP) {
fEnable = true;
} else if(pCmdUI->m_nID == ID_PLAY_FRAMESTEPCANCEL && pFS && pFS->CanStep(0, NULL) == S_OK) {
fEnable = true;
} else if(m_fQuicktimeGraph && pFS) {
fEnable = true;
}
}
pCmdUI->Enable(fEnable);
}
void CMainFrame::OnPlaySeek(UINT nID)
{
AppSettings& s = AfxGetAppSettings();
REFERENCE_TIME dt =
nID == ID_PLAY_SEEKBACKWARDSMALL ? -10000i64*s.nJumpDistS :
nID == ID_PLAY_SEEKFORWARDSMALL ? +10000i64*s.nJumpDistS :
nID == ID_PLAY_SEEKBACKWARDMED ? -10000i64*s.nJumpDistM :
nID == ID_PLAY_SEEKFORWARDMED ? +10000i64*s.nJumpDistM :
nID == ID_PLAY_SEEKBACKWARDLARGE ? -10000i64*s.nJumpDistL :
nID == ID_PLAY_SEEKFORWARDLARGE ? +10000i64*s.nJumpDistL :
0;
if(!dt) {
return;
}
// HACK: the custom graph should support frame based seeking instead
if(m_fShockwaveGraph) {
dt /= 10000i64*100;
}
SeekTo(m_wndSeekBar.GetPos() + dt);
}
void CMainFrame::SetTimersPlay()
{
SetTimer(TIMER_STREAMPOSPOLLER, 40, NULL);
SetTimer(TIMER_STREAMPOSPOLLER2, 500, NULL);
SetTimer(TIMER_STATS, 1000, NULL);
}
void CMainFrame::KillTimersStop()
{
KillTimer(TIMER_STREAMPOSPOLLER2);
KillTimer(TIMER_STREAMPOSPOLLER);
KillTimer(TIMER_STATS);
}
static int rangebsearch(REFERENCE_TIME val, CAtlArray& rta)
{
int i = 0, j = rta.GetCount() - 1, ret = -1;
if(j >= 0 && val >= rta[j]) {
return(j);
}
while(i < j) {
int mid = (i + j) >> 1;
REFERENCE_TIME midt = rta[mid];
if(val == midt) {
ret = mid;
break;
} else if(val < midt) {
ret = -1;
if(j == mid) {
mid--;
}
j = mid;
} else if(val > midt) {
ret = mid;
if(i == mid) {
mid++;
}
i = mid;
}
}
return(ret);
}
void CMainFrame::OnPlaySeekKey(UINT nID)
{
if(m_kfs.GetCount() > 0) {
HRESULT hr;
if(GetMediaState() == State_Stopped) {
SendMessage(WM_COMMAND, ID_PLAY_PAUSE);
}
REFERENCE_TIME rtCurrent, rtDur;
hr = pMS->GetCurrentPosition(&rtCurrent);
hr = pMS->GetDuration(&rtDur);
int dec = 1;
int i = rangebsearch(rtCurrent, m_kfs);
if(i > 0) {
dec = (UINT)max(min(rtCurrent - m_kfs[i-1], 10000000), 0);
}
rtCurrent =
nID == ID_PLAY_SEEKKEYBACKWARD ? max(rtCurrent - dec, 0) :
nID == ID_PLAY_SEEKKEYFORWARD ? rtCurrent : 0;
i = rangebsearch(rtCurrent, m_kfs);
if(nID == ID_PLAY_SEEKKEYBACKWARD) {
rtCurrent = m_kfs[max(i, 0)];
} else if(nID == ID_PLAY_SEEKKEYFORWARD && i < m_kfs.GetCount()-1) {
rtCurrent = m_kfs[i+1];
} else {
return;
}
// HACK: if d3d or something changes fpu control word the values of
// m_kfs may be different now (if it was asked again), adding a little
// to the seek position eliminates this error usually.
rtCurrent += 10;
hr = pMS->SetPositions(
&rtCurrent, AM_SEEKING_AbsolutePositioning|AM_SEEKING_SeekToKeyFrame,
NULL, AM_SEEKING_NoPositioning);
m_OSD.DisplayMessage(OSD_TOPLEFT, m_wndStatusBar.GetStatusTimer(), 1500);
}
}
void CMainFrame::OnUpdatePlaySeek(CCmdUI* pCmdUI)
{
bool fEnable = false;
OAFilterState fs = GetMediaState();
if(m_iMediaLoadState == MLS_LOADED && (fs == State_Paused || fs == State_Running)) {
fEnable = true;
if(GetPlaybackMode() == PM_DVD && (m_iDVDDomain != DVD_DOMAIN_Title || fs != State_Running)) {
fEnable = false;
} else if(GetPlaybackMode() == PM_CAPTURE) {
fEnable = false;
}
}
pCmdUI->Enable(fEnable);
}
void CMainFrame::OnPlayGoto()
{
if ((m_iMediaLoadState != MLS_LOADED) || m_pFullscreenWnd->IsWindow()) {
return;
}
REFTIME atpf = 0;
if(FAILED(pBV->get_AvgTimePerFrame(&atpf)) || atpf < 0) {
atpf = 0;
BeginEnumFilters(pGB, pEF, pBF) {
if(atpf > 0) {
break;
}
BeginEnumPins(pBF, pEP, pPin) {
if(atpf > 0) {
break;
}
AM_MEDIA_TYPE mt;
pPin->ConnectionMediaType(&mt);
if(mt.majortype == MEDIATYPE_Video && mt.formattype == FORMAT_VideoInfo) {
atpf = (REFTIME)((VIDEOINFOHEADER*)mt.pbFormat)->AvgTimePerFrame / 10000000i64;
} else if(mt.majortype == MEDIATYPE_Video && mt.formattype == FORMAT_VideoInfo2) {
atpf = (REFTIME)((VIDEOINFOHEADER2*)mt.pbFormat)->AvgTimePerFrame / 10000000i64;
}
}
EndEnumPins;
}
EndEnumFilters;
}
CGoToDlg dlg((int)(m_wndSeekBar.GetPos()/10000), atpf > 0 ? (float)(1.0/atpf) : 0);
if(IDOK != dlg.DoModal() || dlg.m_time < 0) {
return;
}
SeekTo(10000i64 * dlg.m_time);
}
void CMainFrame::OnUpdateGoto(CCmdUI* pCmdUI)
{
bool fEnable = false;
if(m_iMediaLoadState == MLS_LOADED) {
fEnable = true;
if(GetPlaybackMode() == PM_DVD && m_iDVDDomain != DVD_DOMAIN_Title) {
fEnable = false;
} else if(GetPlaybackMode() == PM_CAPTURE) {
fEnable = false;
}
}
pCmdUI->Enable(fEnable);
}
void CMainFrame::OnPlayChangeRate(UINT nID)
{
if(m_iMediaLoadState != MLS_LOADED) {
return;
}
if(GetPlaybackMode() == PM_CAPTURE) {
if(GetMediaState() != State_Running) {
SendMessage(WM_COMMAND, ID_PLAY_PLAY);
}
long lChannelMin = 0, lChannelMax = 0;
pAMTuner->ChannelMinMax(&lChannelMin, &lChannelMax);
long lChannel = 0, lVivSub = 0, lAudSub = 0;
pAMTuner->get_Channel(&lChannel, &lVivSub, &lAudSub);
long lFreqOrg = 0, lFreqNew = -1;
pAMTuner->get_VideoFrequency(&lFreqOrg);
// long lSignalStrength;
do {
if(nID == ID_PLAY_DECRATE) {
lChannel--;
} else if(nID == ID_PLAY_INCRATE) {
lChannel++;
}
// if(lChannel < lChannelMin) lChannel = lChannelMax;
// if(lChannel > lChannelMax) lChannel = lChannelMin;
if(lChannel < lChannelMin || lChannel > lChannelMax) {
break;
}
if(FAILED(pAMTuner->put_Channel(lChannel, AMTUNER_SUBCHAN_DEFAULT, AMTUNER_SUBCHAN_DEFAULT))) {
break;
}
long flFoundSignal;
pAMTuner->AutoTune(lChannel, &flFoundSignal);
pAMTuner->get_VideoFrequency(&lFreqNew);
} while(FALSE);
/* SUCCEEDED(pAMTuner->SignalPresent(&lSignalStrength))
&& (lSignalStrength != AMTUNER_SIGNALPRESENT || lFreqNew == lFreqOrg));*/
} else {
int iNewSpeedLevel;
// Cap the max FFWD and RWD rates to 128x.
if(nID == ID_PLAY_INCRATE) {
iNewSpeedLevel = (m_iSpeedLevel < 7 ? m_iSpeedLevel+1 : 7);
} else if(nID == ID_PLAY_DECRATE) {
iNewSpeedLevel = (m_iSpeedLevel > -7 ? m_iSpeedLevel-1 : -7);
} else {
return;
}
HRESULT hr = E_FAIL;
if((iNewSpeedLevel == -4) && (GetPlaybackMode() == PM_FILE)) {
if(GetMediaState() != State_Paused) {
SendMessage(WM_COMMAND, ID_PLAY_PAUSE);
}
if(GetMediaState() == State_Paused) {
hr = S_OK;
}
} else {
double dRate = 1.0;
if(GetMediaState() != State_Running) {
SendMessage(WM_COMMAND, ID_PLAY_PLAY);
}
if(GetPlaybackMode() == PM_FILE) {
dRate = pow(2.0, iNewSpeedLevel >= -3 ? iNewSpeedLevel : (-iNewSpeedLevel - 8));
if(fabs(dRate - 1.0) < 0.01) {
dRate = 1.0;
}
hr = pMS->SetRate(dRate);
} else if(GetPlaybackMode() == PM_DVD) {
dRate = pow(2.0, abs(iNewSpeedLevel));
if(iNewSpeedLevel >= 0) {
hr = pDVDC->PlayForwards(dRate, DVD_CMD_FLAG_Block, NULL);
} else {
hr = pDVDC->PlayBackwards(dRate, DVD_CMD_FLAG_Block, NULL);
}
}
if(SUCCEEDED(hr)) {
CString strMessage;
m_iSpeedLevel = iNewSpeedLevel;
if (dRate == 1.0) {
m_OSD.DisplayMessage (OSD_TOPRIGHT, _T("Play"));
} else {
strMessage.Format (_T("%s x %.01f"), (iNewSpeedLevel > 0)?_T(">"):_T("<"), fabs(dRate));
m_OSD.DisplayMessage (OSD_TOPRIGHT, strMessage);
}
}
}
}
}
void CMainFrame::OnUpdatePlayChangeRate(CCmdUI* pCmdUI)
{
bool fEnable = false;
if(m_iMediaLoadState == MLS_LOADED) {
bool fInc = pCmdUI->m_nID == ID_PLAY_INCRATE;
fEnable = true;
if(fInc && m_iSpeedLevel >= 7) {
fEnable = false;
} else if(!fInc && GetPlaybackMode() == PM_FILE && m_iSpeedLevel <= -4) {
fEnable = false;
} else if(!fInc && GetPlaybackMode() == PM_DVD && m_iSpeedLevel <= -11) {
fEnable = false;
} else if(GetPlaybackMode() == PM_DVD && m_iDVDDomain != DVD_DOMAIN_Title) {
fEnable = false;
} else if(m_fRealMediaGraph || m_fShockwaveGraph) {
fEnable = false;
} else if(GetPlaybackMode() == PM_CAPTURE && (!m_wndCaptureBar.m_capdlg.IsTunerActive() || m_fCapturing)) {
fEnable = false;
} else if(m_fLiveWM) {
fEnable = false;
}
}
pCmdUI->Enable(fEnable);
}
void CMainFrame::OnPlayResetRate()
{
if(m_iMediaLoadState != MLS_LOADED) {
return;
}
HRESULT hr = E_FAIL;
if(GetMediaState() != State_Running) {
SendMessage(WM_COMMAND, ID_PLAY_PLAY);
}
if(GetPlaybackMode() == PM_FILE) {
hr = pMS->SetRate(1.0);
} else if(GetPlaybackMode() == PM_DVD) {
hr = pDVDC->PlayForwards(1.0, DVD_CMD_FLAG_Block, NULL);
}
if(SUCCEEDED(hr)) {
m_iSpeedLevel = 0;
}
}
void CMainFrame::OnUpdatePlayResetRate(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED);
}
void CMainFrame::SetAudioDelay(REFERENCE_TIME rtShift)
{
if(CComQIPtr pASF = FindFilter(__uuidof(CAudioSwitcherFilter), pGB)) {
pASF->SetAudioTimeShift(rtShift);
CString str;
str.Format(ResStr(IDS_MAINFRM_70), rtShift/10000);
SendStatusMessage(str, 3000);
m_OSD.DisplayMessage(OSD_TOPLEFT, str);
}
}
void CMainFrame::SetSubtitleDelay(int delay_ms)
{
if(m_pCAP) {
m_pCAP->SetSubtitleDelay(delay_ms);
CString strSubDelay;
strSubDelay.Format (ResStr(IDS_MAINFRM_139), delay_ms);
SendStatusMessage(strSubDelay, 3000);
m_OSD.DisplayMessage (OSD_TOPLEFT, strSubDelay);
}
}
void CMainFrame::OnPlayChangeAudDelay(UINT nID)
{
if(CComQIPtr pASF = FindFilter(__uuidof(CAudioSwitcherFilter), pGB)) {
REFERENCE_TIME rtShift = pASF->GetAudioTimeShift();
rtShift +=
nID == ID_PLAY_INCAUDDELAY ? 100000 :
nID == ID_PLAY_DECAUDDELAY ? -100000 :
0;
SetAudioDelay (rtShift);
}
}
void CMainFrame::OnUpdatePlayChangeAudDelay(CCmdUI* pCmdUI)
{
pCmdUI->Enable(!!pGB /*&& !!FindFilter(__uuidof(CAudioSwitcherFilter), pGB)*/);
}
void CMainFrame::OnPlayFilters(UINT nID)
{
// ShowPPage(m_spparray[nID - ID_FILTERS_SUBITEM_START], m_hWnd);
CComPtr pUnk = m_pparray[nID - ID_FILTERS_SUBITEM_START];
CComPropertySheet ps(ResStr(IDS_PROPSHEET_PROPERTIES), GetModalParent());
if(CComQIPtr pSPP = pUnk) {
ps.AddPages(pSPP);
}
if(CComQIPtr pBF = pUnk) {
HRESULT hr;
CComPtr pPP = DNew CInternalPropertyPageTempl(NULL, &hr);
ps.AddPage(pPP, pBF);
}
if(ps.GetPageCount() > 0) {
ps.DoModal();
OpenSetupStatusBar();
}
}
void CMainFrame::OnUpdatePlayFilters(CCmdUI* pCmdUI)
{
pCmdUI->Enable(!m_fCapturing);
}
enum {
ID_SHADERS_OFF = ID_SHADERS_START,
ID_SHADERS_COMBINE,
ID_SHADERS_EDIT,
ID_SHADERS_STARTSCR,
ID_SHADERS_OFFSCR = ID_SHADERS_STARTSCR,
ID_SHADERS_COMBINESCR,
ID_SHADERS_ENDSCR,
ID_SHADERS_DYNAMIC = ID_SHADERS_ENDSCR,
};
void CMainFrame::OnPlayShaders(UINT nID)
{
if(nID == ID_SHADERS_EDIT) {
ShowControlBar(&m_wndShaderEditorBar, TRUE, TRUE);
return;
}
if(!m_pCAP) {
return;
}
if(nID == ID_SHADERS_OFF) {
m_shaderlabels.RemoveAll();
} else if(nID == ID_SHADERS_OFFSCR) {
m_shaderlabelsScreenSpace.RemoveAll();
} else if(nID == ID_SHADERS_COMBINE) {
if(IDOK != CShaderCombineDlg(m_shaderlabels, GetModalParent(), false).DoModal()) {
return;
}
} else if(nID == ID_SHADERS_COMBINESCR) {
if(IDOK != CShaderCombineDlg(m_shaderlabelsScreenSpace, GetModalParent(), true).DoModal()) {
return;
}
} else if(nID >= ID_SHADERS_DYNAMIC) {
MENUITEMINFO mii;
memset(&mii, 0, sizeof(mii));
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_DATA;
m_shaders.GetMenuItemInfo(nID, &mii);
m_shaderlabels.RemoveAll();
m_shaderlabels.AddTail(((const AppSettings::Shader*)mii.dwItemData)->label);
}
SetShaders();
}
void CMainFrame::OnUpdatePlayShaders(CCmdUI* pCmdUI)
{
if(pCmdUI->m_nID >= ID_SHADERS_START) {
if (pCmdUI->m_nID >= ID_SHADERS_STARTSCR && pCmdUI->m_nID < ID_SHADERS_ENDSCR ) {
pCmdUI->Enable(!!m_pCAP2);
} else {
pCmdUI->Enable(!!m_pCAP);
}
switch(pCmdUI->m_nID) {
case ID_SHADERS_OFF:
pCmdUI->SetRadio(m_shaderlabels.IsEmpty());
break;
case ID_SHADERS_OFFSCR:
pCmdUI->SetRadio(m_shaderlabelsScreenSpace.IsEmpty());
break;
case ID_SHADERS_COMBINE:
pCmdUI->SetRadio(m_shaderlabels.GetCount() > 1);
break;
case ID_SHADERS_COMBINESCR:
pCmdUI->SetRadio(m_shaderlabelsScreenSpace.GetCount() > 0);
break;
case ID_SHADERS_EDIT:
pCmdUI->Enable(TRUE);
break;
default: {
MENUITEMINFO mii;
memset(&mii, 0, sizeof(mii));
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_DATA;
m_shaders.GetMenuItemInfo(pCmdUI->m_nID, &mii);
pCmdUI->SetRadio(m_shaderlabels.GetCount() == 1
&& m_shaderlabels.GetHead() == ((AppSettings::Shader*)mii.dwItemData)->label);
}
break;
}
}
}
void CMainFrame::OnPlayAudio(UINT nID)
{
int i = (int)nID - (1 + ID_AUDIO_SUBITEM_START);
CComQIPtr pSS = FindFilter(__uuidof(CAudioSwitcherFilter), pGB);
if(!pSS) {
pSS = FindFilter(L"{D3CD7858-971A-4838-ACEC-40CA5D529DC8}", pGB);
}
if(i == -1) {
ShowOptions(CPPageAudioSwitcher::IDD);
} else if(i >= 0 && pSS) {
i = m_iAudioStreams.GetAt(m_iAudioStreams.FindIndex(i)); // don't forget that the audio streams are reordered, so have to figure which one from the initial order is used here
pSS->Enable(i, AMSTREAMSELECTENABLE_ENABLE);
}
}
void CMainFrame::OnUpdatePlayAudio(CCmdUI* pCmdUI)
{
UINT nID = pCmdUI->m_nID;
int i = (int)nID - (1 + ID_AUDIO_SUBITEM_START);
CComQIPtr pSS = FindFilter(__uuidof(CAudioSwitcherFilter), pGB);
if(!pSS) {
pSS = FindFilter(L"{D3CD7858-971A-4838-ACEC-40CA5D529DC8}", pGB);
}
/*if(i == -1)
{
// TODO****
}
else*/
if(i >= 0 && pSS) {
i = m_iAudioStreams.GetAt(m_iAudioStreams.FindIndex(i)); // audio streams are reordered, so figure out which one from the initial order is used here
DWORD flags = 0;
if(SUCCEEDED(pSS->Info(i, NULL, &flags, NULL, NULL, NULL, NULL, NULL))) {
if(flags&AMSTREAMSELECTINFO_EXCLUSIVE) {
pCmdUI->SetRadio(TRUE);
} else if(flags&AMSTREAMSELECTINFO_ENABLED) {
pCmdUI->SetCheck(TRUE);
} else {
pCmdUI->SetCheck(FALSE);
}
} else {
pCmdUI->Enable(FALSE);
}
}
}
void CMainFrame::OnPlaySubtitles(UINT nID)
{
int i = (int)nID - (5 + ID_SUBTITLES_SUBITEM_START); // currently the subtitles submenu contains 5 items, apart from the actual subtitles list
if(i == -5) {
// options
ShowOptions(CPPageSubtitles::IDD);
} else if(i == -4) {
// styles
int i = m_iSubtitleSel;
POSITION pos = m_pSubStreams.GetHeadPosition();
while(pos && i >= 0) {
CComPtr pSubStream = m_pSubStreams.GetNext(pos);
if(i < pSubStream->GetStreamCount()) {
CLSID clsid;
if(FAILED(pSubStream->GetClassID(&clsid))) {
continue;
}
if(clsid == __uuidof(CRenderedTextSubtitle)) {
CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)pSubStream;
CAutoPtrArray pages;
CAtlArray styles;
POSITION pos = pRTS->m_styles.GetStartPosition();
for(int i = 0; pos; i++) {
CString key;
STSStyle* val;
pRTS->m_styles.GetNextAssoc(pos, key, val);
CAutoPtr page(DNew CPPageSubStyle());
page->InitStyle(key, *val);
pages.Add(page);
styles.Add(val);
}
CString m_style = ResStr(IDS_SUBTITLES_STYLES);
int i = m_style.Find(_T("&"));
if(i!=-1 ) {
m_style.Delete(i, 1);
}
CPropertySheet dlg(m_style, GetModalParent());
for(int i = 0; i < (int)pages.GetCount(); i++) {
dlg.AddPage(pages[i]);
}
if(dlg.DoModal() == IDOK) {
for(int j = 0; j < (int)pages.GetCount(); j++) {
pages[j]->GetStyle(*styles[j]);
}
UpdateSubtitle(false, false);
}
return;
}
}
i -= pSubStream->GetStreamCount();
}
} else if(i == -3) {
// reload
ReloadSubtitle();
} else if(i == -2) {
// enable
if(m_iSubtitleSel == -1) {
m_iSubtitleSel = 0;
} else {
m_iSubtitleSel ^= (1<<31);
}
UpdateSubtitle();
} else if(i == -1) {
// override default style
// TODO: default subtitles style toggle here
AfxGetAppSettings().fUseDefaultSubtitlesStyle = !AfxGetAppSettings().fUseDefaultSubtitlesStyle;
UpdateSubtitle();
} else if(i >= 0) {
// this is an actual item from the subtitles list
m_iSubtitleSel = i;
UpdateSubtitle();
}
AfxGetAppSettings().fEnableSubtitles = !(m_iSubtitleSel & 0x80000000);
}
void CMainFrame::OnUpdatePlaySubtitles(CCmdUI* pCmdUI)
{
UINT nID = pCmdUI->m_nID;
int i = (int)nID - (5 + ID_SUBTITLES_SUBITEM_START); // again, 5 pre-set subtitles options before the actual list
pCmdUI->Enable(m_pCAP && !m_fAudioOnly);
if(i == -4) {
// styles
pCmdUI->Enable(FALSE);
int i = m_iSubtitleSel;
POSITION pos = m_pSubStreams.GetHeadPosition();
while(pos && i >= 0) {
CComPtr pSubStream = m_pSubStreams.GetNext(pos);
if(i < pSubStream->GetStreamCount()) {
CLSID clsid;
if(FAILED(pSubStream->GetClassID(&clsid))) {
continue;
}
if(clsid == __uuidof(CRenderedTextSubtitle)) {
pCmdUI->Enable(TRUE);
break;
}
}
i -= pSubStream->GetStreamCount();
}
} else if(i == -2) {
// enabled
pCmdUI->SetCheck(AfxGetAppSettings().fEnableSubtitles);
} else if(i == -1) {
// override
// TODO: foxX - default subtitles style toggle here; still wip
pCmdUI->SetCheck(AfxGetAppSettings().fUseDefaultSubtitlesStyle);
pCmdUI->Enable(AfxGetAppSettings().fEnableSubtitles);
} else if(i >= 0) {
pCmdUI->SetRadio(i == abs(m_iSubtitleSel));
}
}
void CMainFrame::OnPlayLanguage(UINT nID)
{
nID -= ID_FILTERSTREAMS_SUBITEM_START;
CComPtr pAMSS = m_ssarray[nID];
UINT i = nID;
while(i > 0 && pAMSS == m_ssarray[i-1]) {
i--;
}
if(FAILED(pAMSS->Enable(nID-i, AMSTREAMSELECTENABLE_ENABLE))) {
MessageBeep((UINT)-1);
}
OpenSetupStatusBar();
}
void CMainFrame::OnUpdatePlayLanguage(CCmdUI* pCmdUI)
{
UINT nID = pCmdUI->m_nID;
nID -= ID_FILTERSTREAMS_SUBITEM_START;
CComPtr pAMSS = m_ssarray[nID];
UINT i = nID;
while(i > 0 && pAMSS == m_ssarray[i-1]) {
i--;
}
DWORD flags = 0;
pAMSS->Info(nID-i, NULL, &flags, NULL, NULL, NULL, NULL, NULL);
if(flags&AMSTREAMSELECTINFO_EXCLUSIVE) {
pCmdUI->SetRadio(TRUE);
} else if(flags&AMSTREAMSELECTINFO_ENABLED) {
pCmdUI->SetCheck(TRUE);
} else {
pCmdUI->SetCheck(FALSE);
}
}
void CMainFrame::OnPlayVolume(UINT nID)
{
if(m_iMediaLoadState == MLS_LOADED) {
CString strVolume;
pBA->put_Volume(m_wndToolBar.Volume);
//strVolume.Format (L"Vol : %d dB", m_wndToolBar.Volume / 100);
if(m_wndToolBar.Volume == -10000) {
strVolume.Format(ResStr(IDS_VOLUME_OSD), 0);
} else {
strVolume.Format(ResStr(IDS_VOLUME_OSD), m_wndToolBar.m_volctrl.GetPos());
}
m_OSD.DisplayMessage(OSD_TOPLEFT, strVolume);
}
m_Lcd.SetVolume((m_wndToolBar.Volume > -10000 ? m_wndToolBar.m_volctrl.GetPos() : 1));
}
void CMainFrame::OnPlayVolumeBoost(UINT nID)
{
AppSettings& s = AfxGetAppSettings();
int i = (int)(s.dAudioBoost_dB*10+0.1);
switch(nID) {
case ID_VOLUME_BOOST_INC:
i = min(i+10, 100);
break;
case ID_VOLUME_BOOST_DEC:
i = max(i-10, 0);
break;
case ID_VOLUME_BOOST_MIN:
i = 0;
break;
case ID_VOLUME_BOOST_MAX:
i = 100;
break;
}
s.dAudioBoost_dB = (float)i/10;
if(CComQIPtr pASF = FindFilter(__uuidof(CAudioSwitcherFilter), pGB)) {
bool fNormalize, fNormalizeRecover;
float boost;
pASF->GetNormalizeBoost(fNormalize, fNormalizeRecover, boost);
pASF->SetNormalizeBoost(fNormalize, fNormalizeRecover, s.dAudioBoost_dB);
}
}
void CMainFrame::OnUpdatePlayVolumeBoost(CCmdUI* pCmdUI)
{
pCmdUI->Enable();
}
void CMainFrame::OnAfterplayback(UINT nID)
{
AppSettings& s = AfxGetAppSettings();
s.nCLSwitches &= ~CLSW_AFTERPLAYBACK_MASK;
switch(nID) {
case ID_AFTERPLAYBACK_NEXT :
s.fNextInDirAfterPlayback = true;
s.fExitAfterPlayback = false;
break;
case ID_AFTERPLAYBACK_EXIT :
s.fExitAfterPlayback = true;
s.fNextInDirAfterPlayback = false;
break;
case ID_AFTERPLAYBACK_DONOTHING:
s.fExitAfterPlayback = false;
s.fNextInDirAfterPlayback = false;
break;
case ID_AFTERPLAYBACK_CLOSE:
s.nCLSwitches |= CLSW_CLOSE;
break;
case ID_AFTERPLAYBACK_STANDBY:
s.nCLSwitches |= CLSW_STANDBY;
break;
case ID_AFTERPLAYBACK_HIBERNATE:
s.nCLSwitches |= CLSW_HIBERNATE;
break;
case ID_AFTERPLAYBACK_SHUTDOWN:
s.nCLSwitches |= CLSW_SHUTDOWN;
break;
case ID_AFTERPLAYBACK_LOGOFF:
s.nCLSwitches |= CLSW_LOGOFF;
break;
}
}
void CMainFrame::OnUpdateAfterplayback(CCmdUI* pCmdUI)
{
AppSettings& s = AfxGetAppSettings();
bool fChecked = false;
switch(pCmdUI->m_nID) {
case ID_AFTERPLAYBACK_EXIT:
fChecked = !!s.fExitAfterPlayback;
break;
case ID_AFTERPLAYBACK_NEXT:
fChecked = !!s.fNextInDirAfterPlayback;
break;
case ID_AFTERPLAYBACK_CLOSE:
fChecked = !!(s.nCLSwitches & CLSW_CLOSE);
break;
case ID_AFTERPLAYBACK_STANDBY:
fChecked = !!(s.nCLSwitches & CLSW_STANDBY);
break;
case ID_AFTERPLAYBACK_HIBERNATE:
fChecked = !!(s.nCLSwitches & CLSW_HIBERNATE);
break;
case ID_AFTERPLAYBACK_SHUTDOWN:
fChecked = !!(s.nCLSwitches & CLSW_SHUTDOWN);
break;
case ID_AFTERPLAYBACK_LOGOFF:
fChecked = !!(s.nCLSwitches & CLSW_LOGOFF);
break;
case ID_AFTERPLAYBACK_DONOTHING:
fChecked = (!s.fExitAfterPlayback) && (!s.fNextInDirAfterPlayback);
break;
}
pCmdUI->SetRadio(fChecked);
}
// navigate
void CMainFrame::OnNavigateSkip(UINT nID)
{
if(GetPlaybackMode() == PM_FILE) {
if(GetPlaybackMode() == PM_FILE) {
SetupChapters();
}
flast_nID = nID;
if(DWORD nChapters = m_pCB->ChapGetCount()) {
REFERENCE_TIME rtCur;
pMS->GetCurrentPosition(&rtCur);
REFERENCE_TIME rt = rtCur;
CComBSTR name;
long i = 0;
if(nID == ID_NAVIGATE_SKIPBACK) {
rt -= 30000000;
i = m_pCB->ChapLookup(&rt, &name);
} else if(nID == ID_NAVIGATE_SKIPFORWARD) {
i = m_pCB->ChapLookup(&rt, &name) + 1;
name.Empty();
if(i < nChapters) {
m_pCB->ChapGet(i, &rt, &name);
}
}
if(i >= 0 && i < nChapters) {
SeekTo(rt);
SendStatusMessage(ResStr(IDS_AG_CHAPTER2) + CString(name), 3000);
REFERENCE_TIME rtDur;
pMS->GetDuration(&rtDur);
CString m_strOSD;
m_strOSD.Format(_T("%s/%s %s%d/%d - \"%s\""), ReftimeToString2(rt), ReftimeToString2(rtDur), ResStr(IDS_AG_CHAPTER2), i+1, nChapters, name);
m_OSD.DisplayMessage(OSD_TOPLEFT, m_strOSD, 3000);
return;
}
}
if(m_wndPlaylistBar.GetCount() != 1) {
if(nID == ID_NAVIGATE_SKIPBACK) {
SendMessage(WM_COMMAND, ID_NAVIGATE_SKIPBACKPLITEM);
} else if(nID == ID_NAVIGATE_SKIPFORWARD) {
SendMessage(WM_COMMAND, ID_NAVIGATE_SKIPFORWARDPLITEM);
}
} else if ((m_wndPlaylistBar.GetCount() == 1) && !AfxGetAppSettings().fDontUseSearchInFolder) {
if(nID == ID_NAVIGATE_SKIPBACK) {
if (!SearchInDir(false)) {
m_OSD.DisplayMessage(OSD_TOPLEFT, ResStr(IDS_FIRST_IN_FOLDER));
}
} else if(nID == ID_NAVIGATE_SKIPFORWARD) {
if (!SearchInDir(true)) {
m_OSD.DisplayMessage(OSD_TOPLEFT, ResStr(IDS_LAST_IN_FOLDER));
}
}
}
} else if(GetPlaybackMode() == PM_DVD) {
m_iSpeedLevel = 0;
if(GetMediaState() != State_Running) {
SendMessage(WM_COMMAND, ID_PLAY_PLAY);
}
ULONG ulNumOfVolumes, ulVolume;
DVD_DISC_SIDE Side;
ULONG ulNumOfTitles = 0;
pDVDI->GetDVDVolumeInfo(&ulNumOfVolumes, &ulVolume, &Side, &ulNumOfTitles);
DVD_PLAYBACK_LOCATION2 Location;
pDVDI->GetCurrentLocation(&Location);
ULONG ulNumOfChapters = 0;
pDVDI->GetNumberOfChapters(Location.TitleNum, &ulNumOfChapters);
if(nID == ID_NAVIGATE_SKIPBACK) {
if(Location.ChapterNum == 1 && Location.TitleNum > 1) {
pDVDI->GetNumberOfChapters(Location.TitleNum-1, &ulNumOfChapters);
pDVDC->PlayChapterInTitle(Location.TitleNum-1, ulNumOfChapters, DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
} else {
ULONG tsec = (Location.TimeCode.bHours * 3600)
+ (Location.TimeCode.bMinutes * 60)
+ (Location.TimeCode.bSeconds);
ULONG diff = 0;
if ( m_lChapterStartTime != 0xFFFFFFFF && tsec > m_lChapterStartTime ) {
diff = tsec - m_lChapterStartTime;
}
// Restart the chapter if more than 7 seconds have passed
if ( diff <= 7 ) {
pDVDC->PlayPrevChapter(DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
} else {
pDVDC->ReplayChapter(DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
}
}
} else if(nID == ID_NAVIGATE_SKIPFORWARD) {
if(Location.ChapterNum == ulNumOfChapters && Location.TitleNum < ulNumOfTitles) {
pDVDC->PlayChapterInTitle(Location.TitleNum+1, 1, DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
} else {
pDVDC->PlayNextChapter(DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
}
}
if((pDVDI->GetCurrentLocation(&Location) == S_OK)) {
pDVDI->GetNumberOfChapters(Location.TitleNum, &ulNumOfChapters);
CString m_strTitle;
m_strTitle.Format(IDS_AG_TITLE, Location.TitleNum);
__int64 start, stop;
m_wndSeekBar.GetRange(start, stop);
CString m_strOSD;
if(stop>0)
m_strOSD.Format(_T("%02d:%02d:%02d/%s %s, %s%d/%d"), Location.TimeCode.bHours, Location.TimeCode.bMinutes, Location.TimeCode.bSeconds,
DVDtimeToString(RT2HMSF(stop)), m_strTitle, ResStr(IDS_AG_CHAPTER2), Location.ChapterNum, ulNumOfChapters);
else {
m_strOSD.Format(_T("%s, %s%d/%d"), m_strTitle, ResStr(IDS_AG_CHAPTER2), Location.ChapterNum, ulNumOfChapters);
}
m_OSD.DisplayMessage(OSD_TOPLEFT, m_strOSD, 3000);
}
/*
if(nID == ID_NAVIGATE_SKIPBACK)
pDVDC->PlayPrevChapter(DVD_CMD_FLAG_Block, NULL);
else if(nID == ID_NAVIGATE_SKIPFORWARD)
pDVDC->PlayNextChapter(DVD_CMD_FLAG_Block, NULL);
*/
} else if(GetPlaybackMode() == PM_CAPTURE) {
if (AfxGetAppSettings().iDefaultCaptureDevice == 1) {
CComQIPtr pTun = pGB;
if (pTun) {
int nCurrentChannel;
AppSettings& s = AfxGetAppSettings();
nCurrentChannel = s.nDVBLastChannel;
if(nID == ID_NAVIGATE_SKIPBACK) {
pTun->SetChannel (nCurrentChannel - 1);
DisplayCurrentChannelOSD();
if (m_wndNavigationBar.IsVisible()) {
m_wndNavigationBar.m_navdlg.UpdatePos(nCurrentChannel - 1);
}
} else if(nID == ID_NAVIGATE_SKIPFORWARD) {
pTun->SetChannel (nCurrentChannel + 1);
DisplayCurrentChannelOSD();
if (m_wndNavigationBar.IsVisible()) {
m_wndNavigationBar.m_navdlg.UpdatePos(nCurrentChannel + 1);
}
}
}
}
}
}
void CMainFrame::OnUpdateNavigateSkip(CCmdUI* pCmdUI)
{
// moved to the timer callback function, that runs less frequent
// if(GetPlaybackMode() == PM_FILE) SetupChapters();
pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED
&& ((GetPlaybackMode() == PM_DVD
&& m_iDVDDomain != DVD_DOMAIN_VideoManagerMenu
&& m_iDVDDomain != DVD_DOMAIN_VideoTitleSetMenu)
|| (GetPlaybackMode() == PM_FILE && !AfxGetAppSettings().fDontUseSearchInFolder)
|| (GetPlaybackMode() == PM_FILE && AfxGetAppSettings().fDontUseSearchInFolder && (m_wndPlaylistBar.GetCount() > 1 || m_pCB->ChapGetCount() > 1))
|| (GetPlaybackMode() == PM_CAPTURE && !m_fCapturing)));
}
void CMainFrame::OnNavigateSkipPlaylistItem(UINT nID)
{
if(GetPlaybackMode() == PM_FILE || GetPlaybackMode() == PM_CAPTURE) {
if(m_wndPlaylistBar.GetCount() == 1) {
SendMessage(WM_COMMAND, ID_PLAY_STOP); // do not remove this, unless you want a circular call with OnPlayPlay()
SendMessage(WM_COMMAND, ID_PLAY_PLAY);
} else {
if(nID == ID_NAVIGATE_SKIPBACKPLITEM) {
m_wndPlaylistBar.SetPrev();
} else if(nID == ID_NAVIGATE_SKIPFORWARDPLITEM) {
m_wndPlaylistBar.SetNext();
}
OpenCurPlaylistItem();
}
}
}
void CMainFrame::OnUpdateNavigateSkipPlaylistItem(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED
&& ((GetPlaybackMode() == PM_FILE || GetPlaybackMode() == PM_CAPTURE && !m_fCapturing) && m_wndPlaylistBar.GetCount() > 1/*0*/));
}
void CMainFrame::OnNavigateMenu(UINT nID)
{
nID -= ID_NAVIGATE_TITLEMENU;
if(m_iMediaLoadState != MLS_LOADED || GetPlaybackMode() != PM_DVD) {
return;
}
m_iSpeedLevel = 0;
if(GetMediaState() != State_Running) {
SendMessage(WM_COMMAND, ID_PLAY_PLAY);
}
pDVDC->ShowMenu((DVD_MENU_ID)(nID+2), DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
}
void CMainFrame::OnUpdateNavigateMenu(CCmdUI* pCmdUI)
{
UINT nID = pCmdUI->m_nID - ID_NAVIGATE_TITLEMENU;
ULONG ulUOPs;
if(m_iMediaLoadState != MLS_LOADED || GetPlaybackMode() != PM_DVD
|| FAILED(pDVDI->GetCurrentUOPS(&ulUOPs))) {
pCmdUI->Enable(FALSE);
return;
}
pCmdUI->Enable(!(ulUOPs & (UOP_FLAG_ShowMenu_Title << nID)));
}
void CMainFrame::OnNavigateAudio(UINT nID)
{
nID -= ID_NAVIGATE_AUDIO_SUBITEM_START;
if(GetPlaybackMode() == PM_FILE || (GetPlaybackMode() == PM_CAPTURE && AfxGetAppSettings().iDefaultCaptureDevice == 1)) {
OnNavStreamSelectSubMenu(nID, 1);
} else if(GetPlaybackMode() == PM_DVD) {
pDVDC->SelectAudioStream(nID, DVD_CMD_FLAG_Block, NULL);
}
}
void CMainFrame::OnNavigateSubpic(UINT nID)
{
if(GetPlaybackMode() == PM_FILE || (GetPlaybackMode() == PM_CAPTURE && AfxGetAppSettings().iDefaultCaptureDevice == 1)) {
OnNavStreamSelectSubMenu(nID - ID_NAVIGATE_SUBP_SUBITEM_START, 2);
} else if(GetPlaybackMode() == PM_DVD) {
int i = (int)nID - (1 + ID_NAVIGATE_SUBP_SUBITEM_START);
if(i == -1) {
ULONG ulStreamsAvailable, ulCurrentStream;
BOOL bIsDisabled;
if(SUCCEEDED(pDVDI->GetCurrentSubpicture(&ulStreamsAvailable, &ulCurrentStream, &bIsDisabled))) {
pDVDC->SetSubpictureState(bIsDisabled, DVD_CMD_FLAG_Block, NULL);
}
} else {
pDVDC->SelectSubpictureStream(i, DVD_CMD_FLAG_Block, NULL);
pDVDC->SetSubpictureState(TRUE, DVD_CMD_FLAG_Block, NULL);
}
}
}
void CMainFrame::OnNavigateAngle(UINT nID)
{
nID -= ID_NAVIGATE_ANGLE_SUBITEM_START;
if(GetPlaybackMode() == PM_FILE) {
OnNavStreamSelectSubMenu(nID, 0);
} else if(GetPlaybackMode() == PM_DVD) {
pDVDC->SelectAngle(nID+1, DVD_CMD_FLAG_Block, NULL);
}
}
void CMainFrame::OnNavigateChapters(UINT nID)
{
nID -= ID_NAVIGATE_CHAP_SUBITEM_START;
if(GetPlaybackMode() == PM_FILE) {
if((int)nID >= 0 && nID < m_pCB->ChapGetCount()) {
REFERENCE_TIME rt;
CComBSTR name;
if(SUCCEEDED(m_pCB->ChapGet(nID, &rt, &name))) {
SeekTo(rt);
SendStatusMessage(ResStr(IDS_AG_CHAPTER2) + CString(name), 3000);
REFERENCE_TIME rtDur;
pMS->GetDuration(&rtDur);
CString m_strOSD;
m_strOSD.Format(_T("%s/%s %s%d/%d - \"%s\""), ReftimeToString2(rt), ReftimeToString2(rtDur), ResStr(IDS_AG_CHAPTER2), nID+1, m_pCB->ChapGetCount(), name);
m_OSD.DisplayMessage(OSD_TOPLEFT, m_strOSD, 3000);
}
return;
}
nID -= m_pCB->ChapGetCount();
if((int)nID >= 0 && (int)nID < m_wndPlaylistBar.GetCount()
&& m_wndPlaylistBar.GetSelIdx() != (int)nID) {
m_wndPlaylistBar.SetSelIdx(nID);
OpenCurPlaylistItem();
}
} else if(GetPlaybackMode() == PM_DVD) {
ULONG ulNumOfVolumes, ulVolume;
DVD_DISC_SIDE Side;
ULONG ulNumOfTitles = 0;
pDVDI->GetDVDVolumeInfo(&ulNumOfVolumes, &ulVolume, &Side, &ulNumOfTitles);
DVD_PLAYBACK_LOCATION2 Location;
pDVDI->GetCurrentLocation(&Location);
ULONG ulNumOfChapters = 0;
pDVDI->GetNumberOfChapters(Location.TitleNum, &ulNumOfChapters);
nID++;
if(nID > 0 && nID <= ulNumOfTitles) {
pDVDC->PlayTitle(nID, DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL); // sometimes this does not do anything ...
pDVDC->PlayChapterInTitle(nID, 1, DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL); // ... but this does!
} else {
nID -= ulNumOfTitles;
if(nID > 0 && nID <= ulNumOfChapters) {
pDVDC->PlayChapter(nID, DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
}
}
if((pDVDI->GetCurrentLocation(&Location) == S_OK)) {
pDVDI->GetNumberOfChapters(Location.TitleNum, &ulNumOfChapters);
CString m_strTitle;
m_strTitle.Format(IDS_AG_TITLE, Location.TitleNum);
__int64 start, stop;
m_wndSeekBar.GetRange(start, stop);
CString m_strOSD;
if(stop>0)
m_strOSD.Format(_T("%02d:%02d:%02d/%s %s, %s%d/%d"), Location.TimeCode.bHours, Location.TimeCode.bMinutes, Location.TimeCode.bSeconds,
DVDtimeToString(RT2HMSF(stop)), m_strTitle, ResStr(IDS_AG_CHAPTER2), Location.ChapterNum, ulNumOfChapters);
else {
m_strOSD.Format(_T("%s, %s%d/%d"), m_strTitle, ResStr(IDS_AG_CHAPTER2), Location.ChapterNum, ulNumOfChapters);
}
m_OSD.DisplayMessage(OSD_TOPLEFT, m_strOSD, 3000);
}
} else if(GetPlaybackMode() == PM_CAPTURE) {
AppSettings& s = AfxGetAppSettings();
if (s.iDefaultCaptureDevice == 1) {
CComQIPtr pTun = pGB;
if (pTun) {
if (s.nDVBLastChannel != nID) {
pTun->SetChannel (nID);
DisplayCurrentChannelOSD();
if (m_wndNavigationBar.IsVisible()) {
m_wndNavigationBar.m_navdlg.UpdatePos(nID);
}
}
}
}
}
}
void CMainFrame::OnNavigateMenuItem(UINT nID)
{
nID -= ID_NAVIGATE_MENU_LEFT;
if(GetPlaybackMode() == PM_DVD) {
switch(nID) {
case 0:
pDVDC->SelectRelativeButton(DVD_Relative_Left);
break;
case 1:
pDVDC->SelectRelativeButton(DVD_Relative_Right);
break;
case 2:
pDVDC->SelectRelativeButton(DVD_Relative_Upper);
break;
case 3:
pDVDC->SelectRelativeButton(DVD_Relative_Lower);
break;
case 4:
if (m_iDVDDomain != DVD_DOMAIN_Title) { // Casimir666 : for the remote control
pDVDC->ActivateButton();
} else {
OnPlayPlay();
}
break;
case 5:
pDVDC->ReturnFromSubmenu(DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
break;
case 6:
pDVDC->Resume(DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
break;
default:
break;
}
} else if (GetPlaybackMode() == PM_FILE) {
OnPlayPlay();
}
}
void CMainFrame::OnUpdateNavigateMenuItem(CCmdUI* pCmdUI)
{
pCmdUI->Enable((m_iMediaLoadState == MLS_LOADED) && ((GetPlaybackMode() == PM_DVD) || (GetPlaybackMode() == PM_FILE)));
}
void CMainFrame::OnTunerScan()
{
CTunerScanDlg Dlg;
Dlg.DoModal();
}
void CMainFrame::OnUpdateTunerScan(CCmdUI* pCmdUI)
{
pCmdUI->Enable((m_iMediaLoadState == MLS_LOADED) &&
(AfxGetAppSettings().iDefaultCaptureDevice == 1) &&
((GetPlaybackMode() == PM_CAPTURE)));
}
// favorites
class CDVDStateStream : public CUnknown, public IStream
{
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv) {
return
QI(IStream)
CUnknown::NonDelegatingQueryInterface(riid, ppv);
}
__int64 m_pos;
public:
CDVDStateStream() : CUnknown(NAME("CDVDStateStream"), NULL) {
m_pos = 0;
}
DECLARE_IUNKNOWN;
CAtlArray m_data;
// ISequentialStream
STDMETHODIMP Read(void* pv, ULONG cb, ULONG* pcbRead) {
__int64 cbRead = min(m_data.GetCount() - m_pos, (__int64)cb);
cbRead = max(cbRead, 0);
memcpy(pv, &m_data[(INT_PTR)m_pos], (int)cbRead);
if(pcbRead) {
*pcbRead = (ULONG)cbRead;
}
m_pos += cbRead;
return S_OK;
}
STDMETHODIMP Write(const void* pv, ULONG cb, ULONG* pcbWritten) {
BYTE* p = (BYTE*)pv;
ULONG cbWritten = (ULONG)-1;
while(++cbWritten < cb) {
m_data.Add(*p++);
}
if(pcbWritten) {
*pcbWritten = cbWritten;
}
return S_OK;
}
// IStream
STDMETHODIMP Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition) {
return E_NOTIMPL;
}
STDMETHODIMP SetSize(ULARGE_INTEGER libNewSize) {
return E_NOTIMPL;
}
STDMETHODIMP CopyTo(IStream* pstm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten) {
return E_NOTIMPL;
}
STDMETHODIMP Commit(DWORD grfCommitFlags) {
return E_NOTIMPL;
}
STDMETHODIMP Revert() {
return E_NOTIMPL;
}
STDMETHODIMP LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {
return E_NOTIMPL;
}
STDMETHODIMP UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {
return E_NOTIMPL;
}
STDMETHODIMP Stat(STATSTG* pstatstg, DWORD grfStatFlag) {
return E_NOTIMPL;
}
STDMETHODIMP Clone(IStream** ppstm) {
return E_NOTIMPL;
}
};
void CMainFrame::OnFavoritesAdd()
{
AppSettings& s = AfxGetAppSettings();
if(GetPlaybackMode() == PM_FILE) {
CString fn = m_wndPlaylistBar.GetCurFileName();
if(fn.IsEmpty()) {
return;
}
CString desc = fn;
desc.Replace('\\', '/');
int i = desc.Find(_T("://")), j = desc.Find(_T("?")), k = desc.ReverseFind('/');
if(i >= 0) {
desc = j >= 0 ? desc.Left(j) : desc;
} else if(k >= 0) {
desc = desc.Mid(k+1);
}
CFavoriteAddDlg dlg(desc, fn);
if(dlg.DoModal() != IDOK) {
return;
}
// Name
CString str = dlg.m_name;
str.Remove(';');
// RememberPos
CString pos(_T("0"));
if(dlg.m_bRememberPos) {
pos.Format(_T("%I64d"), GetPos());
}
str += ';';
str += pos;
// RelativeDrive
CString relativeDrive;
relativeDrive.Format( _T("%d"), dlg.m_bRelativeDrive );
str += ';';
str += relativeDrive;
// Paths
CPlaylistItem pli;
if(m_wndPlaylistBar.GetCur(pli)) {
POSITION pos = pli.m_fns.GetHeadPosition();
while(pos) {
str += _T(";") + pli.m_fns.GetNext(pos);
}
}
s.AddFav(FAV_FILE, str);
} else if(GetPlaybackMode() == PM_DVD) {
WCHAR path[_MAX_PATH];
ULONG len = 0;
pDVDI->GetDVDDirectory(path, _MAX_PATH, &len);
CString fn = path;
fn.TrimRight(_T("/\\"));
DVD_PLAYBACK_LOCATION2 Location;
pDVDI->GetCurrentLocation(&Location);
CString desc;
desc.Format(_T("%s - T%02d C%02d - %02d:%02d:%02d"), fn, Location.TitleNum, Location.ChapterNum,
Location.TimeCode.bHours, Location.TimeCode.bMinutes, Location.TimeCode.bSeconds);
CFavoriteAddDlg dlg(fn, desc);
if(dlg.DoModal() != IDOK) {
return;
}
// Name
CString str = dlg.m_name;
str.Remove(';');
// RememberPos
CString pos(_T("0"));
if(dlg.m_bRememberPos) {
CDVDStateStream stream;
stream.AddRef();
CComPtr pStateData;
CComQIPtr pPersistStream;
if(SUCCEEDED(pDVDI->GetState(&pStateData))
&& (pPersistStream = pStateData)
&& SUCCEEDED(OleSaveToStream(pPersistStream, (IStream*)&stream))) {
pos = BinToCString(stream.m_data.GetData(), stream.m_data.GetCount());
}
}
str += ';';
str += pos;
// Paths
str += ';';
str += fn;
s.AddFav(FAV_DVD, str);
} else if(GetPlaybackMode() == PM_CAPTURE) {
// TODO
}
}
void CMainFrame::OnUpdateFavoritesAdd(CCmdUI* pCmdUI)
{
pCmdUI->Enable(GetPlaybackMode() == PM_FILE || GetPlaybackMode() == PM_DVD);
}
// TODO: OnFavoritesAdd and OnFavoritesQuickAddFavorite use nearly the same code, do something about it
void CMainFrame::OnFavoritesQuickAddFavorite()
{
AppSettings& s = AfxGetAppSettings();
if(GetPlaybackMode() == PM_FILE) {
CString fn = m_wndPlaylistBar.GetCurFileName();
if(fn.IsEmpty()) {
return;
}
CString desc = fn;
desc.Replace('\\', '/');
int i = desc.Find(_T("://")), j = desc.Find(_T("?")), k = desc.ReverseFind('/');
if(i >= 0) {
desc = j >= 0 ? desc.Left(j) : desc;
} else if(k >= 0) {
desc = desc.Mid(k+1);
}
CString fn_with_pos(desc);
if(s.bFavRememberPos) {
fn_with_pos.Format(_T("%s_%s"), desc, GetVidPos()); // Add file position (time format) so it will be easier to organize later
}
// Name
CString str = fn_with_pos;
str.Remove(';');
// RememberPos
CString pos(_T("0"));
if(s.bFavRememberPos) {
pos.Format(_T("%I64d"), GetPos());
}
str += ';';
str += pos;
// RelativeDrive
CString relativeDrive;
relativeDrive.Format( _T("%d"), s.bFavRelativeDrive );
str += ';';
str += relativeDrive;
// Paths
CPlaylistItem pli;
if(m_wndPlaylistBar.GetCur(pli)) {
POSITION pos = pli.m_fns.GetHeadPosition();
while(pos) {
str += _T(";") + pli.m_fns.GetNext(pos);
}
}
s.AddFav(FAV_FILE, str);
} else if(GetPlaybackMode() == PM_DVD) {
WCHAR path[_MAX_PATH];
ULONG len = 0;
pDVDI->GetDVDDirectory(path, _MAX_PATH, &len);
CString fn = path;
fn.TrimRight(_T("/\\"));
DVD_PLAYBACK_LOCATION2 Location;
pDVDI->GetCurrentLocation(&Location);
CString desc;
desc.Format(_T("%s - T%02d C%02d - %02d:%02d:%02d"), fn, Location.TitleNum, Location.ChapterNum,
Location.TimeCode.bHours, Location.TimeCode.bMinutes, Location.TimeCode.bSeconds);
// Name
CString str = s.bFavRememberPos ? desc : fn;
str.Remove(';');
// RememberPos
CString pos(_T("0"));
if(s.bFavRememberPos) {
CDVDStateStream stream;
stream.AddRef();
CComPtr pStateData;
CComQIPtr pPersistStream;
if(SUCCEEDED(pDVDI->GetState(&pStateData))
&& (pPersistStream = pStateData)
&& SUCCEEDED(OleSaveToStream(pPersistStream, (IStream*)&stream))) {
pos = BinToCString(stream.m_data.GetData(), stream.m_data.GetCount());
}
}
str += ';';
str += pos;
// Paths
str += ';';
str += fn;
s.AddFav(FAV_DVD, str);
} else if(GetPlaybackMode() == PM_CAPTURE) {
// TODO
}
}
void CMainFrame::OnFavoritesOrganize()
{
CFavoriteOrganizeDlg dlg;
dlg.DoModal();
}
void CMainFrame::OnUpdateFavoritesOrganize(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
}
void CMainFrame::OnRecentFileClear()
{
if(IDYES != AfxMessageBox(ResStr(IDS_RECENT_FILES_QUESTION), MB_YESNO)) {
return;
}
AppSettings& s = AfxGetAppSettings();
for(int i = 0; i < s.MRU.GetSize(); i++) {
s.MRU[i] = _T("");
}
for(int i = 0; i < s.MRUDub.GetSize(); i++) {
s.MRUDub[i] = _T("");
}
s.MRU.WriteList();
s.MRUDub.WriteList();
}
void CMainFrame::OnUpdateRecentFileClear(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
}
void CMainFrame::OnFavoritesFile(UINT nID)
{
nID -= ID_FAVORITES_FILE_START;
CAtlList sl;
AfxGetAppSettings().GetFav(FAV_FILE, sl);
if(POSITION pos = sl.FindIndex(nID)) {
CAtlList fns;
REFERENCE_TIME rtStart = 0;
BOOL bRelativeDrive = FALSE;
int i = 0, j = 0;
for(CString s1 = sl.GetAt(pos), s2 = s1.Tokenize(_T(";"), i);
!s2.IsEmpty();
s2 = s1.Tokenize(_T(";"), i), j++) {
if(j == 0) {
; // desc / name
} else if(j == 1) {
_stscanf_s(s2, _T("%I64d"), &rtStart); // pos
} else if(j == 2) {
_stscanf_s(s2, _T("%d"), &bRelativeDrive); // relative drive
} else {
fns.AddTail(s2); // paths
}
}
// NOTE: This is just for the favorites but we could add a global settings that does this always when on. Could be useful when using removable devices.
// All you have to do then is plug in your 500 gb drive, full with movies and/or music, start MPC-HC (from the 500 gb drive) with a preloaded playlist and press play.
if ( bRelativeDrive ) {
// Get the drive MPC-HC is on and apply it to the path list
CString exePath;
DWORD dwLength = GetModuleFileName( AfxGetInstanceHandle(), exePath.GetBuffer(_MAX_PATH), _MAX_PATH );
exePath.ReleaseBuffer( dwLength );
CPath exeDrive( exePath );
if ( exeDrive.StripToRoot() ) {
POSITION pos = fns.GetHeadPosition();
while ( pos != NULL ) {
CString &stringPath = fns.GetNext( pos );
CPath path( stringPath );
int rootLength = path.SkipRoot();
if ( path.StripToRoot() ) {
if ( _tcsicmp(exeDrive, path) != 0 ) { // Do we need to replace the drive letter ?
// Replace drive letter
CString newPath( exeDrive );
newPath += stringPath.Mid( rootLength );//newPath += stringPath.Mid( 3 );
stringPath = newPath;
}
}
}
}
}
m_wndPlaylistBar.Open(fns, false);
OpenCurPlaylistItem(max(rtStart, 0));
}
}
void CMainFrame::OnUpdateFavoritesFile(CCmdUI* pCmdUI)
{
UINT nID = pCmdUI->m_nID - ID_FAVORITES_FILE_START;
UNUSED_ALWAYS(nID);
}
void CMainFrame::OnRecentFile(UINT nID)
{
nID -= ID_RECENT_FILE_START;
CString str;
m_recentfiles.GetMenuString(nID+2, str, MF_BYPOSITION);
CAtlList fns;
fns.AddTail(str);
m_wndPlaylistBar.Open(fns, false);
OpenCurPlaylistItem(0);
}
void CMainFrame::OnUpdateRecentFile(CCmdUI* pCmdUI)
{
UINT nID = pCmdUI->m_nID - ID_RECENT_FILE_START;
UNUSED_ALWAYS(nID);
}
void CMainFrame::OnFavoritesDVD(UINT nID)
{
nID -= ID_FAVORITES_DVD_START;
CAtlList sl;
AfxGetAppSettings().GetFav(FAV_DVD, sl);
if(POSITION pos = sl.FindIndex(nID)) {
CString fn;
CDVDStateStream stream;
stream.AddRef();
int i = 0, j = 0;
for(CString s1 = sl.GetAt(pos), s2 = s1.Tokenize(_T(";"), i);
!s2.IsEmpty();
s2 = s1.Tokenize(_T(";"), i), j++) {
if(j == 0) {
; // desc
} else if(j == 1 && s2 != _T("0")) { // state
CStringToBin(s2, stream.m_data);
} else if(j == 2) {
fn = s2; // path
}
}
SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
CComPtr pDvdState;
HRESULT hr = OleLoadFromStream((IStream*)&stream, IID_IDvdState, (void**)&pDvdState);
UNUSED_ALWAYS(hr);
CAutoPtr p(DNew OpenDVDData());
if(p) {
p->path = fn;
p->pDvdState = pDvdState;
}
OpenMedia(p);
}
}
void CMainFrame::OnUpdateFavoritesDVD(CCmdUI* pCmdUI)
{
UINT nID = pCmdUI->m_nID - ID_FAVORITES_DVD_START;
UNUSED_ALWAYS(nID);
}
void CMainFrame::OnFavoritesDevice(UINT nID)
{
nID -= ID_FAVORITES_DEVICE_START;
}
void CMainFrame::OnUpdateFavoritesDevice(CCmdUI* pCmdUI)
{
UINT nID = pCmdUI->m_nID - ID_FAVORITES_DEVICE_START;
UNUSED_ALWAYS(nID);
}
// help
void CMainFrame::OnHelpHomepage()
{
ShellExecute(m_hWnd, _T("open"), _T("http://mpc-hc.sourceforge.net/"), NULL, NULL, SW_SHOWDEFAULT);
}
void CMainFrame::OnHelpDocumentation()
{
ShellExecute(m_hWnd, _T("open"), _T("http://sourceforge.net/project/showfiles.php?group_id=82303&package_id=144472"), NULL, NULL, SW_SHOWDEFAULT);
}
void CMainFrame::OnHelpToolbarImages()
{
ShellExecute(m_hWnd, _T("open"), _T("http://sourceforge.net/apps/trac/mpc-hc/wiki/Toolbar_images"), NULL, NULL, SW_SHOWDEFAULT);
}
/*
void CMainFrame::OnHelpDonate()
{
const TCHAR URL[] = _T("http://sourceforge.net/project/showfiles.php?group_id=170561");
if(CString(URL).Find(CString(_T("A4N")).MakeReverse()) >= 0) {
ShellExecute(m_hWnd, _T("open"), URL, NULL, NULL, SW_SHOWDEFAULT);
}
}
*/
//////////////////////////////////
static BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
{
CAtlArray* ml = (CAtlArray*)dwData;
ml->Add(hMonitor);
return TRUE;
}
void CMainFrame::SetDefaultWindowRect(int iMonitor)
{
AppSettings& s = AfxGetAppSettings();
int w, h, x, y;
if(s.HasFixedWindowSize()) {
w = s.sizeFixedWindow.cx;
h = s.sizeFixedWindow.cy;
} else if(s.fRememberWindowSize) {
w = s.rcLastWindowPos.Width();
h = s.rcLastWindowPos.Height();
} else {
CRect r1, r2;
GetClientRect(&r1);
m_wndView.GetClientRect(&r2);
CSize logosize = m_wndView.GetLogoSize();
int _DEFCLIENTW = max(logosize.cx, DEFCLIENTW);
int _DEFCLIENTH = max(logosize.cy, DEFCLIENTH);
if(GetSystemMetrics(SM_REMOTESESSION)) {
_DEFCLIENTH = 0;
}
DWORD style = GetStyle();
w = _DEFCLIENTW + ((style&WS_THICKFRAME) ? GetSystemMetrics(SM_CXSIZEFRAME)*2 : 0)
+ r1.Width() - r2.Width();
h = _DEFCLIENTH + ((style&WS_THICKFRAME) ? GetSystemMetrics(SM_CYSIZEFRAME)*2 : 0)
+ r1.Height() - r2.Height();
if(style & WS_CAPTION) {
h += GetSystemMetrics(SM_CYCAPTION);
if(s.iCaptionMenuMode == MODE_SHOWCAPTIONMENU)
h += GetSystemMetrics(SM_CYMENU);
//else MODE_HIDEMENU
}
}
bool inmonitor = false;
if(s.fRememberWindowPos) {
CMonitor monitor;
CMonitors monitors;
POINT ptA;
ptA.x = s.rcLastWindowPos.TopLeft().x;
ptA.y = s.rcLastWindowPos.TopLeft().y;
for ( int i = 0; i < monitors.GetCount(); i++ ) {
monitor = monitors.GetMonitor( i );
if(monitor.IsOnMonitor(ptA)) {
inmonitor = true;
break;
}
}
}
if(s.fRememberWindowPos && inmonitor) {
x = s.rcLastWindowPos.TopLeft().x;
y = s.rcLastWindowPos.TopLeft().y;
} else {
HMONITOR hMonitor = MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST);
if(iMonitor > 0) {
iMonitor--;
CAtlArray ml;
EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM)&ml);
if(iMonitor < ml.GetCount()) {
hMonitor = ml[iMonitor];
}
}
MONITORINFO mi;
mi.cbSize = sizeof(MONITORINFO);
GetMonitorInfo(hMonitor, &mi);
x = (mi.rcWork.left+mi.rcWork.right-w)/2; // Center main window
y = (mi.rcWork.top+mi.rcWork.bottom-h)/2; // no need to call CenterWindow()
}
UINT lastWindowType = s.nLastWindowType;
MoveWindow(x, y, w, h);
if (s.iCaptionMenuMode!=MODE_SHOWCAPTIONMENU) {
if (s.iCaptionMenuMode==MODE_FRAMEONLY)
ModifyStyle(WS_CAPTION, 0, SWP_NOZORDER);
else if (s.iCaptionMenuMode==MODE_BORDERLESS)
ModifyStyle(WS_CAPTION | WS_THICKFRAME, 0, SWP_NOZORDER);
::SetMenu(m_hWnd, NULL);
SetWindowPos(NULL, 0, 0, 0, 0, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER);
}
if(!s.fRememberWindowPos) {
CenterWindow();
}
// Waffs : fullscreen command line
if(!(s.nCLSwitches&CLSW_ADD) && (s.nCLSwitches&CLSW_FULLSCREEN) && !s.slFiles.IsEmpty()) {
ToggleFullscreen(true, true);
SetCursor(NULL);
AfxGetAppSettings().nCLSwitches &= ~CLSW_FULLSCREEN;
m_fFirstFSAfterLaunchOnFS = true;
}
if(s.fRememberWindowSize && s.fRememberWindowPos) {
if(lastWindowType == SIZE_MAXIMIZED) {
ShowWindow(SW_MAXIMIZE);
} else if(lastWindowType == SIZE_MINIMIZED) {
ShowWindow(SW_MINIMIZE);
}
// Casimir666 : if fullscreen was on, put it on back
if (!m_fFullScreen && s.fLastFullScreen) {
ToggleFullscreen(true, true);
}
}
}
void CMainFrame::RestoreDefaultWindowRect()
{
AppSettings& s = AfxGetAppSettings();
WINDOWPLACEMENT wp;
GetWindowPlacement(&wp);
if(!m_fFullScreen && wp.showCmd != SW_SHOWMAXIMIZED && wp.showCmd != SW_SHOWMINIMIZED
// && (GetExStyle()&WS_EX_APPWINDOW)
&& !s.fRememberWindowSize) {
int x, y, w, h;
if(s.HasFixedWindowSize()) {
w = s.sizeFixedWindow.cx;
h = s.sizeFixedWindow.cy;
} else {
CRect r1, r2;
GetClientRect(&r1);
m_wndView.GetClientRect(&r2);
CSize logosize = m_wndView.GetLogoSize();
int _DEFCLIENTW = max(logosize.cx, DEFCLIENTW);
int _DEFCLIENTH = max(logosize.cy, DEFCLIENTH);
DWORD style = GetStyle();
w = _DEFCLIENTW + ((style&WS_THICKFRAME) ? GetSystemMetrics(SM_CXSIZEFRAME)*2 : 0)
+ r1.Width() - r2.Width();
h = _DEFCLIENTH + ((style&WS_THICKFRAME) ? GetSystemMetrics(SM_CYSIZEFRAME)*2 : 0)
+ r1.Height() - r2.Height();
if(style & WS_CAPTION) {
h += GetSystemMetrics(SM_CYCAPTION);
if(s.iCaptionMenuMode == MODE_SHOWCAPTIONMENU)
h += GetSystemMetrics(SM_CYMENU);
//else MODE_HIDEMENU
}
}
if(s.fRememberWindowPos) {
x = s.rcLastWindowPos.TopLeft().x;
y = s.rcLastWindowPos.TopLeft().y;
} else {
CRect r;
GetWindowRect(r);
x = r.CenterPoint().x - w/2; // Center window here
y = r.CenterPoint().y - h/2; // no need to call CenterWindow()
}
MoveWindow(x, y, w, h);
if(!s.fRememberWindowPos) {
CenterWindow();
}
}
}
OAFilterState CMainFrame::GetMediaState()
{
OAFilterState ret = -1;
if(m_iMediaLoadState == MLS_LOADED) {
pMC->GetState(0, &ret);
}
return(ret);
}
void CMainFrame::SetPlaybackMode(int iNewStatus)
{
m_iPlaybackMode = iNewStatus;
if (m_wndNavigationBar.IsWindowVisible() && GetPlaybackMode() != PM_CAPTURE) {
ShowControlBar(&m_wndNavigationBar, !m_wndNavigationBar.IsWindowVisible(), TRUE);
}
}
CSize CMainFrame::GetVideoSize()
{
bool fKeepAspectRatio = AfxGetAppSettings().fKeepAspectRatio;
bool fCompMonDeskARDiff = AfxGetAppSettings().fCompMonDeskARDiff;
CSize ret(0,0);
if(m_iMediaLoadState != MLS_LOADED || m_fAudioOnly) {
return ret;
}
CSize wh(0, 0), arxy(0, 0);
if (m_pMFVDC) {
m_pMFVDC->GetNativeVideoSize(&wh, &arxy); // TODO : check AR !!
} else if(m_pCAP) {
wh = m_pCAP->GetVideoSize(false);
arxy = m_pCAP->GetVideoSize(fKeepAspectRatio);
} else {
pBV->GetVideoSize(&wh.cx, &wh.cy);
long arx = 0, ary = 0;
CComQIPtr pBV2 = pBV;
// FIXME: It can hang here, for few seconds (CPU goes to 100%), after the window have been moving over to another screen,
// due to GetPreferredAspectRatio, if it happens before CAudioSwitcherFilter::DeliverEndFlush, it seems.
if(pBV2 && SUCCEEDED(pBV2->GetPreferredAspectRatio(&arx, &ary)) && arx > 0 && ary > 0) {
arxy.SetSize(arx, ary);
}
}
if(wh.cx <= 0 || wh.cy <= 0) {
return ret;
}
// with the overlay mixer IBasicVideo2 won't tell the new AR when changed dynamically
DVD_VideoAttributes VATR;
if(GetPlaybackMode() == PM_DVD && SUCCEEDED(pDVDI->GetCurrentVideoAttributes(&VATR))) {
arxy.SetSize(VATR.ulAspectX, VATR.ulAspectY);
}
CSize& ar = AfxGetAppSettings().sizeAspectRatio;
if(ar.cx && ar.cy) {
arxy = ar;
}
ret = (!fKeepAspectRatio || arxy.cx <= 0 || arxy.cy <= 0)
? wh
: CSize(MulDiv(wh.cy, arxy.cx, arxy.cy), wh.cy);
if(fCompMonDeskARDiff)
if(HDC hDC = ::GetDC(0)) {
int _HORZSIZE = GetDeviceCaps(hDC, HORZSIZE);
int _VERTSIZE = GetDeviceCaps(hDC, VERTSIZE);
int _HORZRES = GetDeviceCaps(hDC, HORZRES);
int _VERTRES = GetDeviceCaps(hDC, VERTRES);
if(_HORZSIZE > 0 && _VERTSIZE > 0 && _HORZRES > 0 && _VERTRES > 0) {
double a = 1.0*_HORZSIZE/_VERTSIZE;
double b = 1.0*_HORZRES/_VERTRES;
if(b < a) {
ret.cy = (DWORD)(1.0*ret.cy * a / b);
} else if(a < b) {
ret.cx = (DWORD)(1.0*ret.cx * b / a);
}
}
::ReleaseDC(0, hDC);
}
return ret;
}
void CMainFrame::ToggleFullscreen(bool fToNearest, bool fSwitchScreenResWhenHasTo)
{
if(m_pFullscreenWnd->IsWindow()) return;
AppSettings& s = AfxGetAppSettings();
CRect r;
DWORD dwRemove = 0, dwAdd = 0;
DWORD dwRemoveEx = 0, dwAddEx = 0;
HMENU hMenu;
MONITORINFO mi;
mi.cbSize = sizeof(MONITORINFO);
HMONITOR hm = MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST);
HMONITOR hm_cur = MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST);
CMonitors monitors;
static bool m_PlayListBarVisible = false;
if(!m_fFullScreen) {
m_PlayListBarVisible = m_wndPlaylistBar.IsVisible();
if(s.bHidePlaylistFullScreen && m_PlayListBarVisible) {
ShowControlBar(&m_wndPlaylistBar, !m_PlayListBarVisible, TRUE);
}
if(!m_fFirstFSAfterLaunchOnFS) {
GetWindowRect(&m_lastWindowRect);
}
if(s.AutoChangeFullscrRes.bEnabled && fSwitchScreenResWhenHasTo && (GetPlaybackMode() != PM_NONE)) {
AutoChangeMonitorMode();
}
m_LastWindow_HM = MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST);
CString str;
CMonitor monitor;
if(s.strFullScreenMonitor == _T("Current")) {
hm = MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST);
} else {
for ( int i = 0; i < monitors.GetCount(); i++ ) {
monitor = monitors.GetMonitor( i );
monitor.GetName(str);
if((monitor.IsMonitor()) && (s.strFullScreenMonitor == str)) {
hm = monitor;
break;
}
}
if(!hm) {
hm = MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST);
}
}
dwRemove = WS_CAPTION|WS_THICKFRAME;
GetMonitorInfo(hm, &mi);
if(fToNearest) {
r = mi.rcMonitor;
} else {
GetDesktopWindow()->GetWindowRect(&r);
}
hMenu = NULL;
} else {
if(s.AutoChangeFullscrRes.bEnabled && s.AutoChangeFullscrRes.bApplyDefault) {
SetDispMode(s.AutoChangeFullscrRes.dmFullscreenResOther, s.strFullScreenMonitor);
}
dwAdd = (s.iCaptionMenuMode==MODE_BORDERLESS ? 0 : s.iCaptionMenuMode==MODE_FRAMEONLY? WS_THICKFRAME: WS_CAPTION | WS_THICKFRAME);
if (!m_fFirstFSAfterLaunchOnFS) {
r = m_lastWindowRect;
}
hMenu = (s.iCaptionMenuMode==MODE_SHOWCAPTIONMENU) ? m_hMenuDefault: NULL;
if(s.bHidePlaylistFullScreen) {
ShowControlBar(&m_wndPlaylistBar, m_PlayListBarVisible, TRUE);
}
}
m_lastMouseMove.x = m_lastMouseMove.y = -1;
bool fAudioOnly = m_fAudioOnly;
m_fAudioOnly = true;
m_fFullScreen = !m_fFullScreen;
s.fLastFullScreen = m_fFullScreen;
SetAlwaysOnTop(s.iOnTop);
ModifyStyle(dwRemove, dwAdd, SWP_NOZORDER);
ModifyStyleEx(dwRemoveEx, dwAddEx, SWP_NOZORDER);
::SetMenu(m_hWnd, hMenu);
static bool m_Change_Monitor = false;
// try disable shader when move from one monitor to other ...
if(m_fFullScreen) {
m_Change_Monitor = (hm != hm_cur);
if((m_Change_Monitor) && (!m_bToggleShader)) {
if (m_pCAP) {
m_pCAP->SetPixelShader(NULL, NULL);
}
}
if((m_Change_Monitor) && (!m_bToggleShaderScreenSpace)) {
if (m_pCAP2) {
m_pCAP2->SetPixelShader2(NULL, NULL, 1);
}
}
} else {
if((m_Change_Monitor) && (!m_bToggleShader)) {
if (m_pCAP) {
m_pCAP->SetPixelShader(NULL, NULL);
}
}
}
if(m_fFullScreen) {
m_fHideCursor = true;
if(s.fShowBarsWhenFullScreen) {
int nTimeOut = s.nShowBarsWhenFullScreenTimeOut;
if(nTimeOut == 0) {
ShowControls(CS_NONE, false);
ShowControlBar(&m_wndNavigationBar, false, TRUE);
} else if(nTimeOut > 0) {
SetTimer(TIMER_FULLSCREENCONTROLBARHIDER, nTimeOut*1000, NULL);
SetTimer(TIMER_FULLSCREENMOUSEHIDER, max(nTimeOut*1000, 2000), NULL);
}
} else {
ShowControls(CS_NONE, false);
ShowControlBar(&m_wndNavigationBar, false, TRUE);
}
if(s.fPreventMinimize) {
if(hm != hm_cur) {
ModifyStyle(WS_MINIMIZEBOX, 0, SWP_NOZORDER);
}
}
} else {
ModifyStyle(0, WS_MINIMIZEBOX, SWP_NOZORDER);
KillTimer(TIMER_FULLSCREENCONTROLBARHIDER);
KillTimer(TIMER_FULLSCREENMOUSEHIDER);
m_fHideCursor = false;
ShowControls(s.nCS);
if (GetPlaybackMode() == PM_CAPTURE && s.iDefaultCaptureDevice == 1) {
ShowControlBar(&m_wndNavigationBar, !s.fHideNavigation, TRUE);
}
}
m_fAudioOnly = fAudioOnly;
if (m_fFirstFSAfterLaunchOnFS) { //Play started in Fullscreen
if(s.fRememberWindowSize || s.fRememberWindowPos) {
r = s.rcLastWindowPos;
if(!s.fRememberWindowPos) {
hm = MonitorFromPoint( CPoint( 0,0 ), MONITOR_DEFAULTTOPRIMARY );
GetMonitorInfo(hm, &mi);
CRect m_r = mi.rcMonitor;
int left = m_r.left + (m_r.Width() - r.Width())/2;
int top = m_r.top + (m_r.Height() - r.Height())/2;
r = CRect(left, top, left + r.Width(), top + r.Height());
}
if(!s.fRememberWindowSize) {
CSize vsize = GetVideoSize();
r = CRect(r.left, r.top, r.left + vsize.cx, r.top + vsize.cy);
ShowWindow(SW_HIDE);
}
SetWindowPos(NULL, r.left, r.top, r.Width(), r.Height(), SWP_NOZORDER|SWP_NOSENDCHANGING);
if(!s.fRememberWindowSize) {
ZoomVideoWindow();
ShowWindow(SW_SHOW);
}
} else {
if(m_LastWindow_HM != hm_cur) {
GetMonitorInfo(m_LastWindow_HM, &mi);
r = mi.rcMonitor;
ShowWindow(SW_HIDE);
SetWindowPos(NULL, r.left, r.top, r.Width(), r.Height(), SWP_NOZORDER|SWP_NOSENDCHANGING);
}
ZoomVideoWindow();
if(m_LastWindow_HM != hm_cur) {
ShowWindow(SW_SHOW);
}
}
m_fFirstFSAfterLaunchOnFS = false;
} else {
SetWindowPos(NULL, r.left, r.top, r.Width(), r.Height(), SWP_NOZORDER|SWP_NOSENDCHANGING);
}
MoveVideoWindow();
if((m_Change_Monitor) && (!m_bToggleShader || !m_bToggleShaderScreenSpace)) { // Enabled shader ...
SetShaders();
}
}
void CMainFrame::AutoChangeMonitorMode()
{
AppSettings& s = AfxGetAppSettings();
CStringW mf_hmonitor = s.strFullScreenMonitor;
double MediaFPS = 0.0;
if (GetPlaybackMode() == PM_FILE) {
LONGLONG m_rtTimePerFrame = 1;
// if ExtractAvgTimePerFrame isn't executed then MediaFPS=10000000.0,
// (int)(MediaFPS + 0.5)=10000000 and SetDispMode is executed to Default.
BeginEnumFilters(pGB, pEF, pBF) {
BeginEnumPins(pBF, pEP, pPin) {
CMediaTypeEx mt;
PIN_DIRECTION dir;
if(FAILED(pPin->QueryDirection(&dir)) || dir != PINDIR_OUTPUT
|| FAILED(pPin->ConnectionMediaType(&mt))) {
continue;
}
ExtractAvgTimePerFrame (&mt, m_rtTimePerFrame);
if (m_rtTimePerFrame == 0) {
m_rtTimePerFrame=1;
}
}
EndEnumPins;
}
EndEnumFilters;
MediaFPS = 10000000.0 / m_rtTimePerFrame;
}
if (GetPlaybackMode() == PM_DVD) {
DVD_PLAYBACK_LOCATION2 Location;
if (pDVDI->GetCurrentLocation(&Location) == S_OK) {
MediaFPS = Location.TimeCodeFlags == DVD_TC_FLAG_25fps ? 25.0
: Location.TimeCodeFlags == DVD_TC_FLAG_30fps ? 30.0
: Location.TimeCodeFlags == DVD_TC_FLAG_DropFrame ? 29.97
: 25.0;
}
}
if (IsVistaOrAbove()) {
if ((MediaFPS > 23.971) && (MediaFPS < 23.981)) {
SetDispMode(s.AutoChangeFullscrRes.dmFullscreenRes23d976Hz, mf_hmonitor);
return;
}
if ((MediaFPS > 29.965) && (MediaFPS < 29.975)) {
SetDispMode(s.AutoChangeFullscrRes.dmFullscreenRes29d97Hz, mf_hmonitor);
return;
}
}
switch ((int)(MediaFPS + 0.5)) {
case 24 :
SetDispMode(s.AutoChangeFullscrRes.dmFullscreenRes24Hz, mf_hmonitor);
break;
case 25 :
SetDispMode(s.AutoChangeFullscrRes.dmFullscreenRes25Hz, mf_hmonitor);
break;
case 30 :
SetDispMode(s.AutoChangeFullscrRes.dmFullscreenRes30Hz, mf_hmonitor);
break;
default:
SetDispMode(s.AutoChangeFullscrRes.dmFullscreenResOther, mf_hmonitor);
}
}
void CMainFrame::MoveVideoWindow(bool fShowStats)
{
if(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly && IsWindowVisible()) {
CRect wr;
if (m_pFullscreenWnd->IsWindow()) {
m_pFullscreenWnd->GetClientRect(&wr);
} else if(!m_fFullScreen) {
m_wndView.GetClientRect(&wr);
} else {
GetWindowRect(&wr);
// it's code need for work in fullscreen on secondary monitor;
CRect r;
m_wndView.GetWindowRect(&r);
wr -= r.TopLeft();
}
CRect vr = CRect(0,0,0,0);
OAFilterState fs = GetMediaState();
if(fs == State_Paused || fs == State_Running || fs == State_Stopped && (m_fShockwaveGraph || m_fQuicktimeGraph)) {
CSize arxy = GetVideoSize();
dvstype iDefaultVideoSize = (dvstype)AfxGetAppSettings().iDefaultVideoSize;
CSize ws =
iDefaultVideoSize == DVS_HALF ? CSize(arxy.cx/2, arxy.cy/2) :
iDefaultVideoSize == DVS_NORMAL ? arxy :
iDefaultVideoSize == DVS_DOUBLE ? CSize(arxy.cx*2, arxy.cy*2) :
wr.Size();
int w = ws.cx;
int h = ws.cy;
if(!m_fShockwaveGraph) { //&& !m_fQuicktimeGraph)
if(iDefaultVideoSize == DVS_FROMINSIDE || iDefaultVideoSize == DVS_FROMOUTSIDE ||
iDefaultVideoSize == DVS_ZOOM1 || iDefaultVideoSize == DVS_ZOOM2) {
int dh = ws.cy;
int dw = MulDiv(dh, arxy.cx, arxy.cy);
int i = 0;
switch(iDefaultVideoSize) {
case DVS_ZOOM1:
i = 1;
break;
case DVS_ZOOM2:
i = 2;
break;
case DVS_FROMOUTSIDE:
i = 3;
break;
}
int minw = dw;
int maxw = dw;
if(ws.cx < dw) {
minw = ws.cx;
} else if(ws.cx > dw) {
maxw = ws.cx;
}
float scale = i / 3.0f;
w = minw + (maxw - minw) * scale;
h = MulDiv(w, arxy.cy, arxy.cx);
}
}
CSize size(
(int)(m_ZoomX*w),
(int)(m_ZoomY*h));
CPoint pos(
(int)(m_PosX*(wr.Width()*3 - m_ZoomX*w) - wr.Width()),
(int)(m_PosY*(wr.Height()*3 - m_ZoomY*h) - wr.Height()));
/* CPoint pos(
(int)(m_PosX*(wr.Width() - size.cx)),
(int)(m_PosY*(wr.Height() - size.cy)));
*/
vr = CRect(pos, size);
}
// What does this do exactly ?
// Add comments when you add this kind of code !
//wr |= CRect(0,0,0,0);
//vr |= CRect(0,0,0,0);
if(m_pCAP) {
m_pCAP->SetPosition(wr, vr);
m_pCAP->SetVideoAngle(Vector(DegToRad(m_AngleX), DegToRad(m_AngleY), DegToRad(m_AngleZ)));
} else {
HRESULT hr;
hr = pBV->SetDefaultSourcePosition();
hr = pBV->SetDestinationPosition(vr.left, vr.top, vr.Width(), vr.Height());
hr = pVW->SetWindowPosition(wr.left, wr.top, wr.Width(), wr.Height());
if (m_pMFVDC) {
m_pMFVDC->SetVideoPosition (NULL, wr);
}
}
m_wndView.SetVideoRect(wr);
if(fShowStats && vr.Height() > 0) {
CString info;
info.Format(_T("Pos %.2f %.2f, Zoom %.2f %.2f, AR %.2f"), m_PosX, m_PosY, m_ZoomX, m_ZoomY, (float)vr.Width()/vr.Height());
SendStatusMessage(info, 3000);
}
} else {
m_wndView.SetVideoRect();
}
UpdateThumbnailClip();
}
void CMainFrame::HideVideoWindow(bool fHide)
{
CRect wr;
if (m_pFullscreenWnd->IsWindow()) {
m_pFullscreenWnd->GetClientRect(&wr);
} else if(!m_fFullScreen) {
m_wndView.GetClientRect(&wr);
} else {
GetWindowRect(&wr);
// this code is needed to work in fullscreen on secondary monitor
CRect r;
m_wndView.GetWindowRect(&r);
wr -= r.TopLeft();
}
CRect vr = CRect(0,0,0,0);
if(m_pCAP) {
if (fHide) {
m_pCAP->SetPosition(wr, vr); //hide
} else {
m_pCAP->SetPosition(wr, wr); // show
}
}
}
void CMainFrame::ZoomVideoWindow(bool snap, double scale)
{
if(m_iMediaLoadState != MLS_LOADED) {
return;
}
AppSettings& s = AfxGetAppSettings();
if(scale <= 0) {
scale =
s.iZoomLevel == 0 ? 0.5 :
s.iZoomLevel == 1 ? 1.0 :
s.iZoomLevel == 2 ? 2.0 :
s.iZoomLevel == 3 ? GetZoomAutoFitScale() :
1.0;
}
if(m_fFullScreen) {
OnViewFullscreen();
}
MINMAXINFO mmi;
OnGetMinMaxInfo(&mmi);
CRect r;
GetWindowRect(r);
int w = 0, h = 0;
if(!m_fAudioOnly) {
CSize arxy = GetVideoSize();
long lWidth = int(arxy.cx * scale + 0.5);
long lHeight = int(arxy.cy * scale + 0.5);
DWORD style = GetStyle();
CRect r1, r2;
GetClientRect(&r1);
m_wndView.GetClientRect(&r2);
w = ((style&WS_THICKFRAME) ? GetSystemMetrics(SM_CXSIZEFRAME)*2 : 0)
+ r1.Width() - r2.Width()
+ lWidth;
h = ((style&WS_THICKFRAME) ? GetSystemMetrics(SM_CYSIZEFRAME)*2 : 0)
+ r1.Height() - r2.Height()
+ lHeight;
if ( style & WS_CAPTION ) {
h += GetSystemMetrics( SM_CYCAPTION );
if(s.iCaptionMenuMode == MODE_SHOWCAPTIONMENU)
h += GetSystemMetrics( SM_CYMENU );
//else MODE_HIDEMENU
}
if (GetPlaybackMode() == PM_CAPTURE && !s.fHideNavigation && !m_fFullScreen && !m_wndNavigationBar.IsVisible()) {
CSize r = m_wndNavigationBar.CalcFixedLayout(FALSE, TRUE);
w += r.cx;
}
w = max(w, mmi.ptMinTrackSize.x);
h = max(h, mmi.ptMinTrackSize.y);
} else {
w = r.Width(); // mmi.ptMinTrackSize.x;
h = mmi.ptMinTrackSize.y;
}
//Prevention of going beyond the scopes of screen
MONITORINFO mi;
mi.cbSize = sizeof(MONITORINFO);
GetMonitorInfo(MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST), &mi);
w = min(w, (mi.rcWork.right - mi.rcWork.left));
h = min(h, (mi.rcWork.bottom - mi.rcWork.top));
if(!s.fRememberWindowPos) {
bool isSnapped = false;
if(snap && s.fSnapToDesktopEdges) { // check if snapped to edges
isSnapped = (r.left == mi.rcWork.left) || (r.top == mi.rcWork.top)
|| (r.right == mi.rcWork.right) || (r.bottom == mi.rcWork.bottom);
}
if(isSnapped) { // prefer left, top snap to right, bottom snap
if(r.left == mi.rcWork.left) {}
else if(r.right == mi.rcWork.right) {
r.left = r.right - w;
}
if(r.top == mi.rcWork.top) {}
else if(r.bottom == mi.rcWork.bottom) {
r.top = r.bottom - h;
}
} else { // center window
CPoint cp = r.CenterPoint();
r.left = cp.x - w/2;
r.top = cp.y - h/2;
}
}
r.right = r.left + w;
r.bottom = r.top + h;
if(r.right > mi.rcWork.right) {
r.OffsetRect(mi.rcWork.right-r.right, 0);
}
if(r.left < mi.rcWork.left) {
r.OffsetRect(mi.rcWork.left-r.left, 0);
}
if(r.bottom > mi.rcWork.bottom) {
r.OffsetRect(0, mi.rcWork.bottom-r.bottom);
}
if(r.top < mi.rcWork.top) {
r.OffsetRect(0, mi.rcWork.top-r.top);
}
if((m_fFullScreen || !s.HasFixedWindowSize()) && !m_pFullscreenWnd->IsWindow()) {
MoveWindow(r);
}
// ShowWindow(SW_SHOWNORMAL);
MoveVideoWindow();
}
double CMainFrame::GetZoomAutoFitScale()
{
if(m_iMediaLoadState != MLS_LOADED || m_fAudioOnly) {
return 1.0;
}
CSize arxy = GetVideoSize();
double sx = 2.0/3 * m_rcDesktop.Width() / arxy.cx;
double sy = 2.0/3 * m_rcDesktop.Height() / arxy.cy;
return sx < sy ? sx : sy;
}
void CMainFrame::RepaintVideo()
{
if(m_pCAP) {
m_pCAP->Paint(false);
}
}
void CMainFrame::SetShaders()
{
if(!m_pCAP) {
return;
}
AppSettings& s = AfxGetAppSettings();
CAtlStringMap s2s;
POSITION pos = s.m_shaders.GetHeadPosition();
while(pos) {
const AppSettings::Shader* pShader = &s.m_shaders.GetNext(pos);
s2s[pShader->label] = pShader;
}
m_pCAP->SetPixelShader(NULL, NULL);
if (m_pCAP2) {
m_pCAP2->SetPixelShader2(NULL, NULL, true);
}
for (int i = 0; i < 2; ++i) {
if (i == 0 && m_bToggleShader) {
continue;
}
if (i == 1 && m_bToggleShaderScreenSpace) {
continue;
}
CAtlList labels;
CAtlList *pLabels;
if (i == 0) {
pLabels = &m_shaderlabels;
} else {
if (!m_pCAP2) {
break;
}
pLabels = &m_shaderlabelsScreenSpace;
}
pos = pLabels->GetHeadPosition();
while(pos) {
const AppSettings::Shader* pShader = NULL;
if(s2s.Lookup(pLabels->GetNext(pos), pShader)) {
CStringA target = pShader->target;
CStringA srcdata = pShader->srcdata;
HRESULT hr;
if (i == 0) {
hr = m_pCAP->SetPixelShader(srcdata, target);
} else {
hr = m_pCAP2->SetPixelShader2(srcdata, target, true);
}
if(FAILED(hr)) {
m_pCAP->SetPixelShader(NULL, NULL);
if (m_pCAP2) {
m_pCAP2->SetPixelShader2(NULL, NULL, true);
}
SendStatusMessage(ResStr(IDS_MAINFRM_73) + pShader->label, 3000);
return;
}
labels.AddTail(pShader->label);
}
}
if(m_iMediaLoadState == MLS_LOADED) {
CString str = Implode(labels, '|');
str.Replace(_T("|"), _T(", "));
SendStatusMessage(ResStr(IDS_AG_SHADER) + str, 3000);
}
}
}
void CMainFrame::UpdateShaders(CString label)
{
if(!m_pCAP) {
return;
}
if(m_shaderlabels.GetCount() <= 1) {
m_shaderlabels.RemoveAll();
}
if(m_shaderlabels.IsEmpty() && !label.IsEmpty()) {
m_shaderlabels.AddTail(label);
}
bool fUpdate = m_shaderlabels.IsEmpty();
POSITION pos = m_shaderlabels.GetHeadPosition();
while(pos) {
if(label == m_shaderlabels.GetNext(pos)) {
fUpdate = true;
break;
}
}
if(fUpdate) {
SetShaders();
}
}
void CMainFrame::SetBalance(int balance)
{
AfxGetAppSettings().nBalance = balance;
int sign = balance>0?-1:1; // -1: invert sign for more right channel
if (balance > -100 && balance < 100)
balance = sign*(int)(100*20*log10(1-abs(balance)/100.0f));
else
balance = sign*(-10000);// -10000: only left, 10000: only right
if(m_iMediaLoadState == MLS_LOADED) {
pBA->put_Balance(balance);
}
}
void CMainFrame::SetupIViAudReg()
{
if(!AfxGetAppSettings().fAutoSpeakerConf) {
return;
}
DWORD spc = 0, defchnum = 0;
if(AfxGetAppSettings().fAutoSpeakerConf) {
CComPtr pDS;
if(SUCCEEDED(DirectSoundCreate(NULL, &pDS, NULL))
&& SUCCEEDED(pDS->SetCooperativeLevel(m_hWnd, DSSCL_NORMAL))) {
if(SUCCEEDED(pDS->GetSpeakerConfig(&spc))) {
switch(spc) {
case DSSPEAKER_DIRECTOUT:
defchnum = 6;
break;
case DSSPEAKER_HEADPHONE:
defchnum = 2;
break;
case DSSPEAKER_MONO:
defchnum = 1;
break;
case DSSPEAKER_QUAD:
defchnum = 4;
break;
default:
case DSSPEAKER_STEREO:
defchnum = 2;
break;
case DSSPEAKER_SURROUND:
defchnum = 2;
break;
case DSSPEAKER_5POINT1:
defchnum = 5;
break;
case DSSPEAKER_7POINT1:
defchnum = 5;
break;
}
}
}
} else {
defchnum = 2;
}
CRegKey iviaud;
if(ERROR_SUCCESS == iviaud.Create(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\InterVideo\\Common\\AudioDec"))) {
DWORD chnum = 0;
if(FAILED(iviaud.QueryDWORDValue(_T("AUDIO"), chnum))) {
chnum = 0;
}
if(chnum <= defchnum) { // check if the user has already set it..., but we won't skip if it's lower than sensible :P
iviaud.SetDWORDValue(_T("AUDIO"), defchnum);
}
}
}
//
// Open/Close
//
bool CMainFrame::IsRealEngineCompatible(CString strFilename) const
{
// Real Media engine didn't support Unicode filename (nor filenames with # characters)
for(int i=0; i126 || Char==35) {
return false;
}
}
return true;
}
void CMainFrame::OpenCreateGraphObject(OpenMediaData* pOMD)
{
ASSERT(pGB == NULL);
m_fCustomGraph = false;
m_fRealMediaGraph = m_fShockwaveGraph = m_fQuicktimeGraph = false;
AppSettings& s = AfxGetAppSettings();
// CASIMIR666 todo
if (s.IsD3DFullscreen() &&
((s.iDSVideoRendererType == VIDRNDT_DS_VMR9RENDERLESS) ||
(s.iDSVideoRendererType == VIDRNDT_DS_EVR_CUSTOM) ||
(s.iDSVideoRendererType == VIDRNDT_DS_MADVR) ||
(s.iDSVideoRendererType == VIDRNDT_DS_SYNC))) {
CreateFullScreenWindow();
m_pVideoWnd = m_pFullscreenWnd;
} else {
m_pVideoWnd = &m_wndView;
}
if(OpenFileData* p = dynamic_cast(pOMD)) {
engine_t engine = s.m_Formats.GetEngine(p->fns.GetHead());
CStringA ct = GetContentType(p->fns.GetHead());
if(ct == "video/x-ms-asf") {
// TODO: put something here to make the windows media source filter load later
} else if(ct == "audio/x-pn-realaudio"
|| ct == "audio/x-pn-realaudio-plugin"
|| ct == "audio/x-realaudio-secure"
|| ct == "video/vnd.rn-realvideo-secure"
|| ct == "application/vnd.rn-realmedia"
|| ct.Find("vnd.rn-") >= 0
|| ct.Find("realaudio") >= 0
|| ct.Find("realvideo") >= 0) {
engine = RealMedia;
} else if(ct == "application/x-shockwave-flash") {
engine = ShockWave;
} else if(ct == "video/quicktime"
|| ct == "application/x-quicktimeplayer") {
engine = QuickTime;
}
HRESULT hr = E_FAIL;
CComPtr pUnk;
if(engine == RealMedia) {
// TODO : see why Real SDK crash here ...
//if (!IsRealEngineCompatible(p->fns.GetHead()))
// throw ResStr(IDS_REALVIDEO_INCOMPATIBLE);
pUnk = (IUnknown*)(INonDelegatingUnknown*)DNew CRealMediaGraph(m_pVideoWnd->m_hWnd, hr);
if(!pUnk) {
throw ResStr(IDS_AG_OUT_OF_MEMORY);
}
if(SUCCEEDED(hr)) {
pGB = CComQIPtr(pUnk);
if(pGB) {
m_fRealMediaGraph = true;
}
}
} else if(engine == ShockWave) {
#ifdef _WIN64 // No flash on x64
MessageBox(ResStr(IDS_MAINFRM_76), _T(""), MB_OK);
#else
pUnk = (IUnknown*)(INonDelegatingUnknown*)DNew CShockwaveGraph(m_pVideoWnd->m_hWnd, hr);
if(!pUnk) {
throw ResStr(IDS_AG_OUT_OF_MEMORY);
}
if(SUCCEEDED(hr)) {
pGB = CComQIPtr(pUnk);
}
if(FAILED(hr) || !pGB) {
throw ResStr(IDS_MAINFRM_77);
}
m_fShockwaveGraph = true;
#endif
} else if(engine == QuickTime) {
#ifdef _WIN64 // TODOX64
// MessageBox (ResStr(IDS_MAINFRM_78), _T(""), MB_OK);
#else
pUnk = (IUnknown*)(INonDelegatingUnknown*)DNew CQuicktimeGraph(m_pVideoWnd->m_hWnd, hr);
if(!pUnk) {
throw ResStr(IDS_AG_OUT_OF_MEMORY);
}
if(SUCCEEDED(hr)) {
pGB = CComQIPtr(pUnk);
if(pGB) {
m_fQuicktimeGraph = true;
}
}
#endif
}
m_fCustomGraph = m_fRealMediaGraph || m_fShockwaveGraph || m_fQuicktimeGraph;
if(!m_fCustomGraph) {
pGB = DNew CFGManagerPlayer(_T("CFGManagerPlayer"), NULL, m_pVideoWnd->m_hWnd);
}
} else if(OpenDVDData* p = dynamic_cast(pOMD)) {
pGB = DNew CFGManagerDVD(_T("CFGManagerDVD"), NULL, m_pVideoWnd->m_hWnd);
} else if(OpenDeviceData* p = dynamic_cast(pOMD)) {
if (s.iDefaultCaptureDevice == 1) {
pGB = DNew CFGManagerBDA(_T("CFGManagerBDA"), NULL, m_pVideoWnd->m_hWnd);
} else {
pGB = DNew CFGManagerCapture(_T("CFGManagerCapture"), NULL, m_pVideoWnd->m_hWnd);
}
}
if(!pGB) {
throw ResStr(IDS_MAINFRM_80);
}
pGB->AddToROT();
pMC = pGB;
pME = pGB;
pMS = pGB; // general
pVW = pGB;
pBV = pGB; // video
pBA = pGB; // audio
pFS = pGB;
if(!(pMC && pME && pMS)
|| !(pVW && pBV)
|| !(pBA)) {
throw _T("Failed to query the needed interfaces for playback");
}
if(FAILED(pME->SetNotifyWindow((OAHWND)m_hWnd, WM_GRAPHNOTIFY, 0))) {
throw _T("Could not set target window for graph notification");
}
m_pProv = (IUnknown*)DNew CKeyProvider();
if(CComQIPtr pObjectWithSite = pGB) {
pObjectWithSite->SetSite(m_pProv);
}
m_pCB = DNew CDSMChapterBag(NULL, NULL);
}
CWnd *CMainFrame::GetModalParent()
{
AppSettings& s = AfxGetAppSettings();
CWnd *pParentWnd = this;
if (m_pFullscreenWnd->IsWindow() && s.m_RenderersSettings.m_RenderSettings.iVMR9FullscreenGUISupport) {
pParentWnd = m_pFullscreenWnd;
}
return pParentWnd;
}
void CMainFrame::OpenFile(OpenFileData* pOFD)
{
if(pOFD->fns.IsEmpty()) {
throw ResStr(IDS_MAINFRM_81);
}
AppSettings& s = AfxGetAppSettings();
bool fFirst = true;
POSITION pos = pOFD->fns.GetHeadPosition();
while(pos) {
CString fn = pOFD->fns.GetNext(pos);
fn.Trim();
if(fn.IsEmpty() && !fFirst) {
break;
}
HRESULT hr = pGB->RenderFile(CStringW(fn), NULL);
if (!s.NewFile (fn) && s.fRememberFilePos) {
REFERENCE_TIME rtPos = s.CurrentFilePosition()->llPosition;
if (pMS) {
pMS->SetPositions (&rtPos, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning);
}
}
QueryPerformanceCounter(&m_LastSaveTime);
if(FAILED(hr)) {
if(fFirst) {
if(s.fReportFailedPins) {
CComQIPtr pGBDE = pGB;
if(pGBDE && pGBDE->GetCount()) {
CMediaTypesDlg(pGBDE, GetModalParent()).DoModal();
}
}
CString err;
switch(hr) {
case E_ABORT:
err = ResStr(IDS_MAINFRM_82);
break;
case E_FAIL:
case E_POINTER:
default:
err = ResStr(IDS_MAINFRM_83);
break;
case E_INVALIDARG:
err = ResStr(IDS_MAINFRM_84);
break;
case E_OUTOFMEMORY:
err = ResStr(IDS_AG_OUT_OF_MEMORY);
break;
case VFW_E_CANNOT_CONNECT:
err = ResStr(IDS_MAINFRM_86);
break;
case VFW_E_CANNOT_LOAD_SOURCE_FILTER:
err = ResStr(IDS_MAINFRM_87);
break;
case VFW_E_CANNOT_RENDER:
err = ResStr(IDS_MAINFRM_88);
break;
case VFW_E_INVALID_FILE_FORMAT:
err = ResStr(IDS_MAINFRM_89);
break;
case VFW_E_NOT_FOUND:
err = ResStr(IDS_MAINFRM_90);
break;
case VFW_E_UNKNOWN_FILE_TYPE:
err = ResStr(IDS_MAINFRM_91);
break;
case VFW_E_UNSUPPORTED_STREAM:
err = ResStr(IDS_MAINFRM_92);
break;
}
throw err;
}
}
if(s.fKeepHistory) {
CRecentFileList* pMRU = fFirst ? &s.MRU : &s.MRUDub;
pMRU->ReadList();
pMRU->Add(fn);
pMRU->WriteList();
SHAddToRecentDocs(SHARD_PATH, fn);
}
if(fFirst) {
pOFD->title = fn;
}
fFirst = false;
if(m_fCustomGraph) {
break;
}
}
if(s.fReportFailedPins) {
CComQIPtr pGBDE = pGB;
if(pGBDE && pGBDE->GetCount()) {
CMediaTypesDlg(pGBDE, GetModalParent()).DoModal();
}
}
if(!(pAMOP = pGB)) {
BeginEnumFilters(pGB, pEF, pBF)
if(pAMOP = pBF) {
break;
}
EndEnumFilters;
}
if(FindFilter(__uuidof(CShoutcastSource), pGB)) {
m_fUpdateInfoBar = true;
}
SetupChapters();
CComQIPtr pKFI;
BeginEnumFilters(pGB, pEF, pBF)
if(pKFI = pBF) {
break;
}
EndEnumFilters;
UINT nKFs = 0, nKFsTmp = 0;
if(pKFI && S_OK == pKFI->GetKeyFrameCount(nKFs) && nKFs > 0) {
m_kfs.SetCount(nKFsTmp = nKFs);
if(S_OK != pKFI->GetKeyFrames(&TIME_FORMAT_MEDIA_TIME, m_kfs.GetData(), nKFsTmp) || nKFsTmp != nKFs) {
m_kfs.RemoveAll();
}
}
SetPlaybackMode(PM_FILE);
}
void CMainFrame::SetupChapters()
{
ASSERT(m_pCB);
m_pCB->ChapRemoveAll();
CInterfaceList pBFs;
BeginEnumFilters(pGB, pEF, pBF)
pBFs.AddTail(pBF);
EndEnumFilters;
POSITION pos;
pos = pBFs.GetHeadPosition();
while(pos && !m_pCB->ChapGetCount()) {
IBaseFilter* pBF = pBFs.GetNext(pos);
CComQIPtr pCB = pBF;
if(!pCB) {
continue;
}
for(DWORD i = 0, cnt = pCB->ChapGetCount(); i < cnt; i++) {
REFERENCE_TIME rt;
CComBSTR name;
if(SUCCEEDED(pCB->ChapGet(i, &rt, &name))) {
m_pCB->ChapAppend(rt, name);
}
}
}
pos = pBFs.GetHeadPosition();
while(pos && !m_pCB->ChapGetCount()) {
IBaseFilter* pBF = pBFs.GetNext(pos);
CComQIPtr pCI = pBF;
if(!pCI) {
continue;
}
CHAR iso6391[3];
::GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SISO639LANGNAME, iso6391, 3);
CStringA iso6392 = ISO6391To6392(iso6391);
if(iso6392.GetLength() < 3) {
iso6392 = "eng";
}
UINT cnt = pCI->GetChapterCount(CHAPTER_ROOT_ID);
for(UINT i = 1; i <= cnt; i++) {
UINT cid = pCI->GetChapterId(CHAPTER_ROOT_ID, i);
ChapterElement ce;
if(pCI->GetChapterInfo(cid, &ce)) {
char pl[3] = {iso6392[0], iso6392[1], iso6392[2]};
char cc[] = " ";
CComBSTR name;
name.Attach(pCI->GetChapterStringInfo(cid, pl, cc));
m_pCB->ChapAppend(ce.rtStart, name);
}
}
}
pos = pBFs.GetHeadPosition();
while(pos && !m_pCB->ChapGetCount()) {
IBaseFilter* pBF = pBFs.GetNext(pos);
CComQIPtr pES = pBF;
if(!pES) {
continue;
}
long MarkerCount = 0;
if(SUCCEEDED(pES->get_MarkerCount(&MarkerCount))) {
for(long i = 1; i <= MarkerCount; i++) {
double MarkerTime = 0;
if(SUCCEEDED(pES->GetMarkerTime(i, &MarkerTime))) {
CStringW name;
name.Format(L"Chapter %d", i);
CComBSTR bstr;
if(S_OK == pES->GetMarkerName(i, &bstr)) {
name = bstr;
}
m_pCB->ChapAppend(REFERENCE_TIME(MarkerTime*10000000), name);
}
}
}
}
pos = pBFs.GetHeadPosition();
while(pos && !m_pCB->ChapGetCount()) {
IBaseFilter* pBF = pBFs.GetNext(pos);
if(GetCLSID(pBF) != CLSID_OggSplitter) {
continue;
}
BeginEnumPins(pBF, pEP, pPin) {
if(m_pCB->ChapGetCount()) {
break;
}
if(CComQIPtr pPB = pPin) {
for(int i = 1; ; i++) {
CStringW str;
CComVariant var;
var.Clear();
str.Format(L"CHAPTER%02d", i);
if(S_OK != pPB->Read(str, &var, NULL)) {
break;
}
int h, m, s, ms;
WCHAR wc;
if(7 != swscanf_s(CStringW(var), L"%d%c%d%c%d%c%d", &h, &wc, &m, &wc, &s, &wc, &ms)) {
break;
}
CStringW name;
name.Format(L"Chapter %d", i);
var.Clear();
str += L"NAME";
if(S_OK == pPB->Read(str, &var, NULL)) {
name = var;
}
m_pCB->ChapAppend(10000i64*(((h*60 + m)*60 + s)*1000 + ms), name);
}
}
}
EndEnumPins;
}
m_pCB->ChapSort();
}
void CMainFrame::OpenDVD(OpenDVDData* pODD)
{
HRESULT hr = pGB->RenderFile(CStringW(pODD->path), NULL);
AppSettings& s = AfxGetAppSettings();
if(s.fReportFailedPins) {
CComQIPtr pGBDE = pGB;
if(pGBDE && pGBDE->GetCount()) {
CMediaTypesDlg(pGBDE, GetModalParent()).DoModal();
}
}
BeginEnumFilters(pGB, pEF, pBF) {
if((pDVDC = pBF) && (pDVDI = pBF)) {
break;
}
}
EndEnumFilters;
if(hr == E_INVALIDARG) {
throw ResStr(IDS_MAINFRM_93);
} else if(hr == VFW_E_CANNOT_RENDER) {
throw _T("Failed to render all pins of the DVD Navigator filter");
} else if(hr == VFW_S_PARTIAL_RENDER) {
throw _T("Failed to render some of the pins of the DVD Navigator filter");
} else if(hr == E_NOINTERFACE || !pDVDC || !pDVDI) {
throw _T("Failed to query the needed interfaces for DVD playback");
} else if(hr == VFW_E_CANNOT_LOAD_SOURCE_FILTER) {
throw ResStr(IDS_MAINFRM_94);
} else if(FAILED(hr)) {
throw ResStr(IDS_AG_FAILED);
}
WCHAR buff[_MAX_PATH];
ULONG len = 0;
if(SUCCEEDED(hr = pDVDI->GetDVDDirectory(buff, countof(buff), &len))) {
pODD->title = CString(CStringW(buff));
}
// TODO: resetdvd
pDVDC->SetOption(DVD_ResetOnStop, FALSE);
pDVDC->SetOption(DVD_HMSF_TimeCodeEvents, TRUE);
if(s.idMenuLang) {
pDVDC->SelectDefaultMenuLanguage(s.idMenuLang);
}
if(s.idAudioLang) {
pDVDC->SelectDefaultAudioLanguage(s.idAudioLang, DVD_AUD_EXT_NotSpecified);
}
if(s.idSubtitlesLang) {
pDVDC->SelectDefaultSubpictureLanguage(s.idSubtitlesLang, DVD_SP_EXT_NotSpecified);
}
m_iDVDDomain = DVD_DOMAIN_Stop;
SetPlaybackMode(PM_DVD);
}
HRESULT CMainFrame::OpenBDAGraph()
{
HRESULT hr = pGB->RenderFile (L"",L"");
if (!FAILED(hr)) {
AddTextPassThruFilter();
SetPlaybackMode(PM_CAPTURE);
}
return hr;
}
void CMainFrame::OpenCapture(OpenDeviceData* pODD)
{
CStringW vidfrname, audfrname;
CComPtr pVidCapTmp, pAudCapTmp;
m_VidDispName = pODD->DisplayName[0];
if(!m_VidDispName.IsEmpty()) {
if(!CreateFilter(m_VidDispName, &pVidCapTmp, vidfrname)) {
throw ResStr(IDS_MAINFRM_96);
}
}
m_AudDispName = pODD->DisplayName[1];
if(!m_AudDispName.IsEmpty()) {
if(!CreateFilter(m_AudDispName, &pAudCapTmp, audfrname)) {
throw ResStr(IDS_MAINFRM_96);
}
}
if(!pVidCapTmp && !pAudCapTmp) {
throw ResStr(IDS_MAINFRM_98);
}
pCGB = NULL;
pVidCap = NULL;
pAudCap = NULL;
if(FAILED(pCGB.CoCreateInstance(CLSID_CaptureGraphBuilder2))) {
throw ResStr(IDS_MAINFRM_99);
}
HRESULT hr;
pCGB->SetFiltergraph(pGB);
if(pVidCapTmp) {
if(FAILED(hr = pGB->AddFilter(pVidCapTmp, vidfrname))) {
throw _T("Can't add video capture filter to the graph");
}
pVidCap = pVidCapTmp;
if(!pAudCapTmp) {
if(FAILED(pCGB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Interleaved, pVidCap, IID_IAMStreamConfig, (void **)&pAMVSCCap))
&& FAILED(pCGB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pVidCap, IID_IAMStreamConfig, (void **)&pAMVSCCap))) {
TRACE(_T("Warning: No IAMStreamConfig interface for vidcap capture"));
}
if(FAILED(pCGB->FindInterface(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Interleaved, pVidCap, IID_IAMStreamConfig, (void **)&pAMVSCPrev))
&& FAILED(pCGB->FindInterface(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, pVidCap, IID_IAMStreamConfig, (void **)&pAMVSCPrev))) {
TRACE(_T("Warning: No IAMStreamConfig interface for vidcap capture"));
}
if(FAILED(pCGB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, pVidCap, IID_IAMStreamConfig, (void **)&pAMASC))
&& FAILED(pCGB->FindInterface(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Audio, pVidCap, IID_IAMStreamConfig, (void **)&pAMASC))) {
TRACE(_T("Warning: No IAMStreamConfig interface for vidcap"));
} else {
pAudCap = pVidCap;
}
} else {
if(FAILED(pCGB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pVidCap, IID_IAMStreamConfig, (void **)&pAMVSCCap))) {
TRACE(_T("Warning: No IAMStreamConfig interface for vidcap capture"));
}
if(FAILED(pCGB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pVidCap, IID_IAMStreamConfig, (void **)&pAMVSCPrev))) {
TRACE(_T("Warning: No IAMStreamConfig interface for vidcap capture"));
}
}
if(FAILED(pCGB->FindInterface(&LOOK_UPSTREAM_ONLY, NULL, pVidCap, IID_IAMCrossbar, (void**)&pAMXBar))) {
TRACE(_T("Warning: No IAMCrossbar interface was found\n"));
}
if(FAILED(pCGB->FindInterface(&LOOK_UPSTREAM_ONLY, NULL, pVidCap, IID_IAMTVTuner, (void**)&pAMTuner))) {
TRACE(_T("Warning: No IAMTVTuner interface was found\n"));
}
/*
if(pAMVSCCap)
{
//DumpStreamConfig(_T("c:\\mpclog.txt"), pAMVSCCap);
CComQIPtr pVfwCD = pVidCap;
if(!pAMXBar && pVfwCD)
{
m_wndCaptureBar.m_capdlg.SetupVideoControls(viddispname, pAMVSCCap, pVfwCD);
}
else
{
m_wndCaptureBar.m_capdlg.SetupVideoControls(viddispname, pAMVSCCap, pAMXBar, pAMTuner);
}
}
*/
// TODO: init pAMXBar
if(pAMTuner) { // load saved channel
pAMTuner->put_CountryCode(AfxGetApp()->GetProfileInt(_T("Capture"), _T("Country"), 1));
int vchannel = pODD->vchannel;
if(vchannel < 0) {
vchannel = AfxGetApp()->GetProfileInt(_T("Capture\\") + CString(m_VidDispName), _T("Channel"), -1);
}
if(vchannel >= 0) {
OAFilterState fs = State_Stopped;
pMC->GetState(0, &fs);
if(fs == State_Running) {
pMC->Pause();
}
pAMTuner->put_Channel(vchannel, AMTUNER_SUBCHAN_DEFAULT, AMTUNER_SUBCHAN_DEFAULT);
if(fs == State_Running) {
pMC->Run();
}
}
}
}
if(pAudCapTmp) {
if(FAILED(hr = pGB->AddFilter(pAudCapTmp, CStringW(audfrname)))) {
throw _T("Can't add audio capture filter to the graph");
}
pAudCap = pAudCapTmp;
if(FAILED(pCGB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, pAudCap, IID_IAMStreamConfig, (void **)&pAMASC))
&& FAILED(pCGB->FindInterface(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Audio, pAudCap, IID_IAMStreamConfig, (void **)&pAMASC))) {
TRACE(_T("Warning: No IAMStreamConfig interface for vidcap"));
}
/*
CInterfaceArray pAMAIM;
BeginEnumPins(pAudCap, pEP, pPin)
{
PIN_DIRECTION dir;
if(FAILED(pPin->QueryDirection(&dir)) || dir != PINDIR_INPUT)
continue;
if(CComQIPtr pAIM = pPin)
pAMAIM.Add(pAIM);
}
EndEnumPins;
if(pAMASC)
{
m_wndCaptureBar.m_capdlg.SetupAudioControls(auddispname, pAMASC, pAMAIM);
}
*/
}
if(!(pVidCap || pAudCap)) {
throw ResStr(IDS_MAINFRM_108);
}
pODD->title = _T("Live");
SetPlaybackMode(PM_CAPTURE);
}
void CMainFrame::OpenCustomizeGraph()
{
if(GetPlaybackMode() == PM_CAPTURE) {
return;
}
CleanGraph();
if(GetPlaybackMode() == PM_FILE) {
if(m_pCAP && AfxGetAppSettings().fAutoloadSubtitles) {
AddTextPassThruFilter();
}
}
AppSettings& s = AfxGetAppSettings();
CRenderersSettings& r = s.m_RenderersSettings;
if (r.m_RenderSettings.bSynchronizeVideo && s.iDSVideoRendererType == VIDRNDT_DS_SYNC) {
HRESULT hr;
m_pRefClock = DNew CSyncClockFilter(NULL, &hr);
CStringW name;
name.Format(L"SyncClock Filter");
pGB->AddFilter(m_pRefClock, name);
CComPtr refClock;
m_pRefClock->QueryInterface(IID_IReferenceClock, reinterpret_cast(&refClock));
CComPtr mediaFilter;
pGB->QueryInterface(IID_IMediaFilter, reinterpret_cast(&mediaFilter));
mediaFilter->SetSyncSource(refClock);
mediaFilter = NULL;
refClock = NULL;
m_pRefClock->QueryInterface(IID_ISyncClock, reinterpret_cast(&m_pSyncClock));
CComQIPtr pAdviser = m_pCAP;
if (pAdviser) {
pAdviser->AdviseSyncClock(m_pSyncClock);
}
}
if(GetPlaybackMode() == PM_DVD) {
BeginEnumFilters(pGB, pEF, pBF) {
if(CComQIPtr pDVS2 = pBF) {
// pDVS2->AdviseSubClock(m_pSubClock = DNew CSubClock);
// break;
// TODO: test multiple dvobsub instances with one clock
if(!m_pSubClock) {
m_pSubClock = DNew CSubClock;
}
pDVS2->AdviseSubClock(m_pSubClock);
}
}
EndEnumFilters;
}
BeginEnumFilters(pGB, pEF, pBF) {
if(GetCLSID(pBF) == CLSID_OggSplitter) {
if(CComQIPtr pSS = pBF) {
LCID idAudio = s.idAudioLang;
if(!idAudio) {
idAudio = GetUserDefaultLCID();
}
LCID idSub = s.idSubtitlesLang;
if(!idSub) {
idSub = GetUserDefaultLCID();
}
DWORD cnt = 0;
pSS->Count(&cnt);
for(DWORD i = 0; i < cnt; i++) {
AM_MEDIA_TYPE* pmt = NULL;
DWORD dwFlags = 0;
LCID lcid = 0;
DWORD dwGroup = 0;
WCHAR* pszName = NULL;
if(SUCCEEDED(pSS->Info((long)i, &pmt, &dwFlags, &lcid, &dwGroup, &pszName, NULL, NULL))) {
CStringW name(pszName), sound(ResStr(IDS_AG_SOUND)), subtitle(L"Subtitle");
if(idAudio != (LCID)-1 && (idAudio&0x3ff) == (lcid&0x3ff) // sublang seems to be zeroed out in ogm...
&& name.GetLength() > sound.GetLength()
&& !name.Left(sound.GetLength()).CompareNoCase(sound)) {
if(SUCCEEDED(pSS->Enable(i, AMSTREAMSELECTENABLE_ENABLE))) {
idAudio = (LCID)-1;
}
}
if(idSub != (LCID)-1 && (idSub&0x3ff) == (lcid&0x3ff) // sublang seems to be zeroed out in ogm...
&& name.GetLength() > subtitle.GetLength()
&& !name.Left(subtitle.GetLength()).CompareNoCase(subtitle)
&& name.Mid(subtitle.GetLength()).Trim().CompareNoCase(L"off")) {
if(SUCCEEDED(pSS->Enable(i, AMSTREAMSELECTENABLE_ENABLE))) {
idSub = (LCID)-1;
}
}
if(pmt) {
DeleteMediaType(pmt);
}
if(pszName) {
CoTaskMemFree(pszName);
}
}
}
}
}
}
EndEnumFilters;
CleanGraph();
}
void CMainFrame::OpenSetupVideo()
{
m_fAudioOnly = true;
if (m_pMFVDC) { // EVR
m_fAudioOnly = false;
} else if(m_pCAP) {
CSize vs = m_pCAP->GetVideoSize();
m_fAudioOnly = (vs.cx <= 0 || vs.cy <= 0);
} else {
{
long w = 0, h = 0;
if(CComQIPtr pBV = pGB) {
pBV->GetVideoSize(&w, &h);
}
if(w > 0 && h > 0) {
m_fAudioOnly = false;
}
}
if(m_fAudioOnly) {
BeginEnumFilters(pGB, pEF, pBF) {
long w = 0, h = 0;
if(CComQIPtr pVW = pBF) {
long lVisible;
if(FAILED(pVW->get_Visible(&lVisible))) {
continue;
}
pVW->get_Width(&w);
pVW->get_Height(&h);
}
if(w > 0 && h > 0) {
m_fAudioOnly = false;
break;
}
}
EndEnumFilters;
}
}
if(m_fShockwaveGraph) {
m_fAudioOnly = false;
}
if(m_pCAP) {
SetShaders();
}
// else
{
// TESTME
pVW->put_Owner((OAHWND)m_pVideoWnd->m_hWnd);
pVW->put_WindowStyle(WS_CHILD|WS_CLIPSIBLINGS|WS_CLIPCHILDREN);
pVW->put_MessageDrain((OAHWND)m_hWnd);
for(CWnd* pWnd = m_wndView.GetWindow(GW_CHILD); pWnd; pWnd = pWnd->GetNextWindow()) {
pWnd->EnableWindow(FALSE); // little trick to let WM_SETCURSOR thru
}
}
if (m_fAudioOnly && m_pFullscreenWnd->IsWindow()) {
m_pFullscreenWnd->DestroyWindow();
}
}
void CMainFrame::OpenSetupAudio()
{
pBA->put_Volume(m_wndToolBar.Volume);
// FIXME
int balance = AfxGetAppSettings().nBalance;
int sign = balance>0?-1:1; // -1: invert sign for more right channel
if (balance > -100 && balance < 100)
balance = sign*(int)(100*20*log10(1-abs(balance)/100.0f));
else
balance = sign*(-10000);// -10000: only left, 10000: only right
pBA->put_Balance(balance);
}
/*
void CMainFrame::OpenSetupToolBar()
{
// m_wndToolBar.Volume = AfxGetAppSettings().nVolume;
// SetBalance(AfxGetAppSettings().nBalance);
}
*/
void CMainFrame::OpenSetupCaptureBar()
{
if(GetPlaybackMode() == PM_CAPTURE) {
if(pVidCap && pAMVSCCap) {
CComQIPtr pVfwCD = pVidCap;
if(!pAMXBar && pVfwCD) {
m_wndCaptureBar.m_capdlg.SetupVideoControls(m_VidDispName, pAMVSCCap, pVfwCD);
} else {
m_wndCaptureBar.m_capdlg.SetupVideoControls(m_VidDispName, pAMVSCCap, pAMXBar, pAMTuner);
}
}
if(pAudCap && pAMASC) {
CInterfaceArray pAMAIM;
BeginEnumPins(pAudCap, pEP, pPin) {
if(CComQIPtr pAIM = pPin) {
pAMAIM.Add(pAIM);
}
}
EndEnumPins;
m_wndCaptureBar.m_capdlg.SetupAudioControls(m_AudDispName, pAMASC, pAMAIM);
}
}
BuildGraphVideoAudio(
m_wndCaptureBar.m_capdlg.m_fVidPreview, false,
m_wndCaptureBar.m_capdlg.m_fAudPreview, false);
}
void CMainFrame::OpenSetupInfoBar()
{
if(GetPlaybackMode() == PM_FILE) {
bool fEmpty = true;
BeginEnumFilters(pGB, pEF, pBF) {
if(CComQIPtr pAMMC = pBF) {
CComBSTR bstr;
if(SUCCEEDED(pAMMC->get_Title(&bstr))) {
m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_TITLE), bstr.m_str);
if(bstr.Length()) {
fEmpty = false;
}
}
bstr.Empty();
if(SUCCEEDED(pAMMC->get_AuthorName(&bstr))) {
m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_AUTHOR), bstr.m_str);
if(bstr.Length()) {
fEmpty = false;
}
}
bstr.Empty();
if(SUCCEEDED(pAMMC->get_Copyright(&bstr))) {
m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_COPYRIGHT), bstr.m_str);
if(bstr.Length()) {
fEmpty = false;
}
}
bstr.Empty();
if(SUCCEEDED(pAMMC->get_Rating(&bstr))) {
m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_RATING), bstr.m_str);
if(bstr.Length()) {
fEmpty = false;
}
}
bstr.Empty();
if(SUCCEEDED(pAMMC->get_Description(&bstr))) {
m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_DESCRIPTION), bstr.m_str);
if(bstr.Length()) {
fEmpty = false;
}
}
bstr.Empty();
if(!fEmpty) {
RecalcLayout();
break;
}
}
}
EndEnumFilters;
} else if(GetPlaybackMode() == PM_DVD) {
CString info('-');
m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_DOMAIN), info);
m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_LOCATION), info);
m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_VIDEO), info);
m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_AUDIO), info);
m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_SUBTITLES), info);
RecalcLayout();
}
}
void CMainFrame::OpenSetupStatsBar()
{
CString info('-');
BeginEnumFilters(pGB, pEF, pBF) {
if(!pQP && (pQP = pBF)) {
m_wndStatsBar.SetLine(ResStr(IDS_AG_FRAMERATE), info);
m_wndStatsBar.SetLine(_T("Sync Offset"), info);
m_wndStatsBar.SetLine(ResStr(IDS_AG_FRAMES), info);
m_wndStatsBar.SetLine(_T("Jitter"), info);
m_wndStatsBar.SetLine(ResStr(IDS_AG_BUFFERS), info);
m_wndStatsBar.SetLine(_T("Bitrate"), info);
RecalcLayout();
}
if(!pBI && (pBI = pBF)) {
m_wndStatsBar.SetLine(ResStr(IDS_AG_BUFFERS), info);
m_wndStatsBar.SetLine(_T("Bitrate"), info); // FIXME: shouldn't be here
RecalcLayout();
}
}
EndEnumFilters;
}
void CMainFrame::OpenSetupStatusBar()
{
m_wndStatusBar.ShowTimer(true);
//
if(!m_fCustomGraph) {
UINT id = IDB_NOAUDIO;
BeginEnumFilters(pGB, pEF, pBF) {
CComQIPtr pBA = pBF;
if(!pBA) {
continue;
}
BeginEnumPins(pBF, pEP, pPin) {
if(S_OK == pGB->IsPinDirection(pPin, PINDIR_INPUT)
&& S_OK == pGB->IsPinConnected(pPin)) {
AM_MEDIA_TYPE mt;
memset(&mt, 0, sizeof(mt));
pPin->ConnectionMediaType(&mt);
if(mt.majortype == MEDIATYPE_Audio && mt.formattype == FORMAT_WaveFormatEx) {
switch(((WAVEFORMATEX*)mt.pbFormat)->nChannels) {
case 1:
id = IDB_MONO;
break;
case 2:
default:
id = IDB_STEREO;
break;
}
break;
} else if(mt.majortype == MEDIATYPE_Midi) {
id = NULL;
break;
}
}
}
EndEnumPins;
if(id != IDB_NOAUDIO) {
break;
}
}
EndEnumFilters;
m_wndStatusBar.SetStatusBitmap(id);
}
//
HICON hIcon = NULL;
if(GetPlaybackMode() == PM_FILE) {
CString fn = m_wndPlaylistBar.GetCurFileName();
CString ext = fn.Mid(fn.ReverseFind('.')+1);
hIcon = LoadIcon(ext, true);
} else if(GetPlaybackMode() == PM_DVD) {
hIcon = LoadIcon(_T(".ifo"), true);
} else if(GetPlaybackMode() == PM_DVD) {
// hIcon = ; // TODO
}
m_wndStatusBar.SetStatusTypeIcon(hIcon);
}
void CMainFrame::OpenSetupWindowTitle(CString fn)
{
CString title(MAKEINTRESOURCE(IDR_MAINFRAME));
AppSettings& s = AfxGetAppSettings();
int i = s.iTitleBarTextStyle;
if(!fn.IsEmpty() && (i == 0 || i == 1)) {
if(i == 1) {
if(GetPlaybackMode() == PM_FILE) {
fn.Replace('\\', '/');
CString fn2 = fn.Mid(fn.ReverseFind('/')+1);
if(!fn2.IsEmpty()) {
fn = fn2;
}
if(s.fTitleBarTextTitle) {
BeginEnumFilters(pGB, pEF, pBF) {
if(CComQIPtr pAMMC = pBF) {
CComBSTR bstr;
if(SUCCEEDED(pAMMC->get_Title(&bstr)) && bstr.Length()) {
fn = CString(bstr.m_str);
break;
}
}
}
EndEnumFilters;
}
} else if(GetPlaybackMode() == PM_DVD) {
fn = _T("DVD");
} else if(GetPlaybackMode() == PM_CAPTURE) {
fn = _T("Live");
}
}
title = fn;
}
SetWindowText(title);
m_Lcd.SetMediaTitle(LPCTSTR(fn));
}
// foxX: simply global now, figures out if, based on the options selected by the user
// the language of audio stream a from pSS is more ``important" than that of audio b
bool DoesAudioPrecede(const CComPtr &pSS, int a, int b)
{
WCHAR* pName = NULL;
if(FAILED(pSS->Info(a, NULL, NULL, NULL, NULL, &pName, NULL, NULL))) {
return false;
}
CString nameA(pName);
CoTaskMemFree(pName);
if(FAILED(pSS->Info(b, NULL, NULL, NULL, NULL, &pName, NULL, NULL))) {
return false;
}
CString nameB(pName);
CoTaskMemFree(pName);
int ia = -1;
int ib = -1;
CStringW alo = AfxGetAppSettings().strAudiosLanguageOrder;
int tPos = 0;
CStringW lang = alo.Tokenize(_T(",; "), tPos);
while(tPos != -1 && ia == -1 && ib == -1) {
int ll = lang.GetLength();
if(nameA.Left(ll).CompareNoCase(lang) == 0) {
ia = tPos;
}
if(nameB.Left(ll).CompareNoCase(lang) == 0) {
ib = tPos;
}
lang = alo.Tokenize(_T(",; "), tPos);
}
if(ia != -1 && ib == -1) {
return true;
}
return false;
}
// foxX: does the naive insertion, in a separate list of audio streams indexes, of stream number i
// from the original ordering of audio streams, based on language order preference
void CMainFrame::InsertAudioStream(const CComQIPtr &pSS, int i)
{
POSITION pos = m_iAudioStreams.GetHeadPosition();
bool processed = false;
while(!processed && pos) {
POSITION prevPos = pos;
int j = m_iAudioStreams.GetNext(pos);
if(DoesAudioPrecede(pSS, i, j)) {
if(prevPos == m_iAudioStreams.GetHeadPosition()) {
m_iAudioStreams.AddHead(i);
} else {
m_iAudioStreams.InsertBefore(prevPos, i);
}
processed = true;
}
}
if(!processed) {
m_iAudioStreams.AddTail(i);
}
}
// foxX: creates a mapping of audio streams, where they're ordered based on their language and the user language order options
void CMainFrame::SetupAudioStreams()
{
if(m_iMediaLoadState != MLS_LOADED) {
return;
}
m_iAudioStreams.RemoveAll();
CComQIPtr 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 > 0) {
for(int i = 0; i < (int)cStreams; i++) {
InsertAudioStream(pSS, i);
}
}
}
bool CMainFrame::OpenMediaPrivate(CAutoPtr pOMD)
{
AppSettings& s = AfxGetAppSettings();
if(m_iMediaLoadState != MLS_CLOSED) {
ASSERT(0);
return(false);
}
OpenFileData *pFileData = dynamic_cast(pOMD.m_p);
OpenDVDData* pDVDData = dynamic_cast(pOMD.m_p);
OpenDeviceData* pDeviceData = dynamic_cast(pOMD.m_p);
if(!pFileData && !pDVDData && !pDeviceData) {
ASSERT(0);
return(false);
}
#ifdef _DEBUG
// Debug trace code - Begin
// Check for bad / buggy auto loading file code
if ( pFileData ) {
POSITION pos = pFileData->fns.GetHeadPosition();
UINT index = 0;
while ( pos != NULL ) {
CString path = pFileData->fns.GetNext( pos );
TRACE(_T("--> CMainFrame::OpenMediaPrivate - pFileData->fns[%d]:\n"), index);
TRACE(_T("\t%ws\n"), path.GetString()); // %ws - wide character string always
index++;
}
}
// Debug trace code - End
#endif
if(pFileData) {
if(pFileData->fns.IsEmpty()) {
return(false);
}
CString fn = pFileData->fns.GetHead();
int i = fn.Find(_T(":\\"));
if(i > 0) {
CString drive = fn.Left(i+2);
UINT type = GetDriveType(drive);
CAtlList sl;
if(type == DRIVE_REMOVABLE || type == DRIVE_CDROM && GetCDROMType(drive[0], sl) != CDROM_Audio) {
int ret = IDRETRY;
while(ret == IDRETRY) {
WIN32_FIND_DATA findFileData;
HANDLE h = FindFirstFile(fn, &findFileData);
if(h != INVALID_HANDLE_VALUE) {
FindClose(h);
ret = IDOK;
} else {
CString msg;
msg.Format(ResStr(IDS_MAINFRM_114), fn);
ret = AfxMessageBox(msg, MB_RETRYCANCEL);
}
}
if(ret != IDOK) {
return(false);
}
}
}
}
SetLoadState (MLS_LOADING);
// FIXME: Don't show "Closed" initially
PostMessage(WM_KICKIDLE);
CString err, aborted(ResStr(IDS_AG_ABORTED));
m_fUpdateInfoBar = false;
BeginWaitCursor();
try {
CComPtr pVMB;
CComPtr pMFVMB;
CComPtr pMVTO;
if(m_fOpeningAborted) {
throw aborted;
}
OpenCreateGraphObject(pOMD);
if(m_fOpeningAborted) {
throw aborted;
}
SetupIViAudReg();
if(m_fOpeningAborted) {
throw aborted;
}
if(pFileData) {
OpenFile(pFileData);
} else if(pDVDData) {
OpenDVD(pDVDData);
} else if(pDeviceData) {
if (s.iDefaultCaptureDevice == 1) {
HRESULT hr = OpenBDAGraph();
if FAILED(hr) {
throw _T("Could not open capture device.");
}
} else {
OpenCapture(pDeviceData);
}
} else {
throw _T("Can't open, invalid input parameters");
}
m_pCAP2 = NULL;
m_pCAP = NULL;
pGB->FindInterface(__uuidof(ISubPicAllocatorPresenter), (void**)&m_pCAP, TRUE);
pGB->FindInterface(__uuidof(ISubPicAllocatorPresenter2), (void**)&m_pCAP2, TRUE);
pGB->FindInterface(__uuidof(IVMRMixerControl9), (void**)&m_pMC, TRUE);
pGB->FindInterface(__uuidof(IVMRMixerBitmap9), (void**)&pVMB, TRUE);
pGB->FindInterface(__uuidof(IMFVideoMixerBitmap), (void**)&pMFVMB, TRUE);
pMVTO = m_pCAP;
if (pMVTO && s.fShowOSD) {
m_OSD.Start (m_pVideoWnd, pMVTO);
} else if (pVMB && s.fShowOSD) {
m_OSD.Start (m_pVideoWnd, pVMB);
} else if (pMFVMB && s.fShowOSD) {
m_OSD.Start (m_pVideoWnd, pMFVMB);
}
if (m_pMC) {
m_pMC->GetProcAmpControlRange (0, (VMR9ProcAmpControlRange*)AfxGetMyApp()->GetColorControl (Brightness));
m_pMC->GetProcAmpControlRange (0, (VMR9ProcAmpControlRange*)AfxGetMyApp()->GetColorControl (Contrast));
m_pMC->GetProcAmpControlRange (0, (VMR9ProcAmpControlRange*)AfxGetMyApp()->GetColorControl (Hue));
m_pMC->GetProcAmpControlRange (0, (VMR9ProcAmpControlRange*)AfxGetMyApp()->GetColorControl (Saturation));
SetVMR9ColorControl(s.dBrightness, s.dContrast, s.dHue, s.dSaturation);
}
// === EVR !
pGB->FindInterface(__uuidof(IMFVideoDisplayControl), (void**)&m_pMFVDC, TRUE);
if (m_pMFVDC) {
RECT Rect;
::GetClientRect (m_pVideoWnd->m_hWnd, &Rect);
m_pMFVDC->SetVideoWindow (m_pVideoWnd->m_hWnd);
m_pMFVDC->SetVideoPosition(NULL, &Rect);
}
if(m_fOpeningAborted) {
throw aborted;
}
OpenCustomizeGraph();
if(m_fOpeningAborted) {
throw aborted;
}
OpenSetupVideo();
if(m_fOpeningAborted) {
throw aborted;
}
OpenSetupAudio();
if(m_fOpeningAborted) {
throw aborted;
}
if(m_pCAP && (!m_fAudioOnly || m_fRealMediaGraph)) {
int nInternalSubCount = m_pSubStreams.GetCount();
if(s.fDisableInternalSubtitles && nInternalSubCount > 0) {
m_pSubStreams.RemoveAll(); // Needs to be replaced with code that checks for forced subtitles.
// Update the the internal subtitle count
nInternalSubCount = m_pSubStreams.GetCount();
}
POSITION pos = pOMD->subs.GetHeadPosition();
while(pos) {
LoadSubtitle(pOMD->subs.GetNext(pos));
}
if(AfxGetAppSettings().fEnableSubtitles && m_pSubStreams.GetCount() > 0) {
CComPtr pSub = m_pSubStreams.GetHead();
if(s.fPrioritizeExternalSubtitles && m_pSubStreams.GetCount() > nInternalSubCount) {
int nCurrentSubIndex = -1;
POSITION pos = m_pSubStreams.GetHeadPosition();
while(pos) {
pSub = m_pSubStreams.GetNext(pos);
nCurrentSubIndex++;
if(nCurrentSubIndex == nInternalSubCount) {
break;
}
}
}
SetSubtitle(pSub);
}
}
if(m_fOpeningAborted) {
throw aborted;
}
OpenSetupWindowTitle(pOMD->title);
if (s.fEnableEDLEditor) {
m_wndEditListEditor.OpenFile(pOMD->title);
}
if(pFileData) {
m_OpenFile = true;
}
if(::GetCurrentThreadId() == AfxGetApp()->m_nThreadID) {
OnFilePostOpenmedia();
} else {
PostMessage(WM_COMMAND, ID_FILE_POST_OPENMEDIA);
}
while(m_iMediaLoadState != MLS_LOADED
&& m_iMediaLoadState != MLS_CLOSING // FIXME
) {
Sleep(50);
}
SetupAudioStreams(); // reorder audio streams so that they're according to user's options
// PostMessage instead of SendMessage because the user might call CloseMedia and then we would deadlock
PostMessage(WM_COMMAND, ID_PLAY_PAUSE);
if(!(AfxGetAppSettings().nCLSwitches&CLSW_OPEN) && (AfxGetAppSettings().nLoops > 0)) {
PostMessage(WM_COMMAND, ID_PLAY_PLAY);
}
// Casimir666 : audio selection should be done before running the graph to prevent an
// unnecessary seek when a file is opened (PostMessage ID_AUDIO_SUBITEM_START removed)
if(m_iAudioStreams.GetCount() > 0) {
OnPlayAudio (ID_AUDIO_SUBITEM_START + 1);
}
AfxGetAppSettings().nCLSwitches &= ~CLSW_OPEN;
if(pFileData) {
if(pFileData->rtStart > 0) {
PostMessage(WM_RESUMEFROMSTATE, (WPARAM)PM_FILE, (LPARAM)(pFileData->rtStart/10000)); // REFERENCE_TIME doesn't fit in LPARAM under a 32bit env.
}
} else if(pDVDData) {
if(pDVDData->pDvdState) {
PostMessage(WM_RESUMEFROMSTATE, (WPARAM)PM_DVD, (LPARAM)(CComPtr(pDVDData->pDvdState).Detach())); // must be released by the called message handler
}
} else if(pDeviceData) {
m_wndCaptureBar.m_capdlg.SetVideoInput(pDeviceData->vinput);
m_wndCaptureBar.m_capdlg.SetVideoChannel(pDeviceData->vchannel);
m_wndCaptureBar.m_capdlg.SetAudioInput(pDeviceData->ainput);
}
} catch(LPCTSTR msg) {
err = msg;
} catch(CString msg) {
err = msg;
}
EndWaitCursor();
if(!err.IsEmpty()) {
CloseMediaPrivate();
m_closingmsg = err;
if(err != aborted) {
if(pFileData) {
m_wndPlaylistBar.SetCurValid(false);
if(m_wndPlaylistBar.GetCount() > 1) {
if(flast_nID == ID_NAVIGATE_SKIPBACK) {
m_wndPlaylistBar.SetPrev();
} else {
m_wndPlaylistBar.SetNext();
}
OpenCurPlaylistItem();
}
} else {
OnNavigateSkip(ID_NAVIGATE_SKIPFORWARD);
}
}
} else {
m_wndPlaylistBar.SetCurValid(true);
// Apply command line audio shift
if (s.rtShift != 0) {
SetAudioDelay (s.rtShift);
s.rtShift = 0;
}
}
flast_nID = 0;
if (AfxGetAppSettings().AutoChangeFullscrRes.bEnabled && m_fFullScreen) {
AutoChangeMonitorMode();
}
if (m_fFullScreen && AfxGetAppSettings().fRememberZoomLevel) {
m_fFirstFSAfterLaunchOnFS = true;
}
m_LastOpenFile = pOMD->title;
PostMessage(WM_KICKIDLE); // calls main thread to update things
CString m_strOSD = _T("");
if(pFileData) {
m_strOSD = m_wndPlaylistBar.GetCurFileName();
if(m_strOSD != _T("")) {
m_strOSD.TrimRight('/');
m_strOSD.Replace('\\', '/');
m_strOSD = m_strOSD.Mid(m_strOSD.ReverseFind('/')+1);
} else {
m_strOSD = ResStr(ID_PLAY_PLAY);
int i = m_strOSD.Find(_T("\n"));
if(i > 0) {
m_strOSD.Delete(i, m_strOSD.GetLength()-i);
}
m_strOSD += _T(" BD");
}
} else if(pDVDData) {
m_strOSD = ResStr(ID_PLAY_PLAY);
int i = m_strOSD.Find(_T("\n"));
if(i > 0) {
m_strOSD.Delete(i, m_strOSD.GetLength()-i);
}
m_strOSD += _T(" DVD");
}
if(m_strOSD != _T("")) {
Sleep(500);
m_OSD.DisplayMessage(OSD_TOPLEFT, m_strOSD, 3000);
}
return(err.IsEmpty());
}
void CMainFrame::CloseMediaPrivate()
{
SetLoadState (MLS_CLOSING);
OnPlayStop(); // SendMessage(WM_COMMAND, ID_PLAY_STOP);
SetPlaybackMode(PM_NONE);
m_iSpeedLevel = 0;
m_fLiveWM = false;
m_fEndOfStream = false;
m_rtDurationOverride = -1;
m_kfs.RemoveAll();
m_pCB = NULL;
// if(pVW) pVW->put_Visible(OAFALSE);
// if(pVW) pVW->put_MessageDrain((OAHWND)NULL), pVW->put_Owner((OAHWND)NULL);
m_pCAP = NULL; // IMPORTANT: IVMRSurfaceAllocatorNotify/IVMRSurfaceAllocatorNotify9 has to be released before the VMR/VMR9, otherwise it will crash in Release()
m_pCAP2 = NULL;
m_pMC = NULL;
m_pMFVDC = NULL;
m_pSyncClock = NULL;
m_OSD.Stop();
pAMXBar.Release();
pAMTuner.Release();
pAMDF.Release();
pAMVCCap.Release();
pAMVCPrev.Release();
pAMVSCCap.Release();
pAMVSCPrev.Release();
pAMASC.Release();
pVidCap.Release();
pAudCap.Release();
pCGB.Release();
pDVDC.Release();
pDVDI.Release();
pQP.Release();
pBI.Release();
pAMOP.Release();
pFS.Release();
pMC.Release();
pME.Release();
pMS.Release();
pVW.Release();
pBV.Release();
pBA.Release();
if(pGB) {
pGB->RemoveFromROT();
pGB.Release();
}
if (m_pFullscreenWnd->IsWindow()) {
m_pFullscreenWnd->DestroyWindow(); // TODO : still freezing sometimes...
}
m_fRealMediaGraph = m_fShockwaveGraph = m_fQuicktimeGraph = false;
m_pSubClock = NULL;
m_pProv.Release();
{
CAutoLock cAutoLock(&m_csSubLock);
m_pSubStreams.RemoveAll();
}
m_VidDispName.Empty();
m_AudDispName.Empty();
m_closingmsg = ResStr(IDS_CONTROLS_CLOSED);
AfxGetAppSettings().nCLSwitches &= CLSW_OPEN|CLSW_PLAY|CLSW_AFTERPLAYBACK_MASK|CLSW_NOFOCUS;
AfxGetAppSettings().ResetPositions();
SetLoadState (MLS_CLOSED);
}
typedef struct {
CString fn;
} fileName;
int compare(const void* arg1, const void* arg2)
{
return StrCmpLogicalW(((fileName*)arg1)->fn, ((fileName*)arg2)->fn);
}
int CMainFrame::SearchInDir(bool DirForward)
{
CAtlList Play_sl;
CAtlList sl;
CAtlArray f_array;
Play_sl.RemoveAll();
sl.RemoveAll();
CMediaFormats& mf = AfxGetAppSettings().m_Formats;
CString dir = m_LastOpenFile.Mid(0,m_LastOpenFile.ReverseFind('\\')+1);
CString mask = dir + _T("*.*");
WIN32_FIND_DATA fd;
HANDLE h = FindFirstFile(mask, &fd);
if(h != INVALID_HANDLE_VALUE) {
do {
if(fd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) {
continue;
}
CString fn = fd.cFileName;
CString ext = fn.Mid(fn.ReverseFind('.')).MakeLower();
CString path = dir + fd.cFileName;
if(mf.FindExt(ext) && mf.GetCount() > 0) {
fileName f_name;
f_name.fn = path;
f_array.Add(f_name);
}
} while(FindNextFile(h, &fd));
FindClose(h);
}
if(f_array.GetCount() == 1) {
return true;
}
qsort(f_array.GetData(), f_array.GetCount(), sizeof(fileName), compare);
for(int i = 0; i < f_array.GetCount(); i++) {
sl.AddTail(f_array[i].fn);
}
POSITION Pos;
Pos = sl.Find(m_LastOpenFile);
if (DirForward) {
if (Pos == sl.GetTailPosition()) {
return(false);
}
sl.GetNext(Pos);
} else {
if (Pos == sl.GetHeadPosition()) {
return(false);
}
sl.GetPrev(Pos);
}
Play_sl.AddHead(sl.GetAt(Pos));
m_wndPlaylistBar.Open(Play_sl,false);
OpenCurPlaylistItem();
return(sl.GetCount());
}
void CMainFrame::DoTunerScan(TunerScanData* pTSD)
{
if(GetPlaybackMode() == PM_CAPTURE) {
CComQIPtr pTun = pGB;
if (pTun) {
BOOLEAN bPresent;
BOOLEAN bLocked;
LONG lStrength;
LONG lQuality;
int nProgress;
int nOffset = pTSD->Offset ? 3 : 1;
LONG lOffsets[3] = {0, pTSD->Offset, -pTSD->Offset};
bool bSucceeded;
m_bStopTunerScan = false;
for(ULONG ulFrequency = pTSD->FrequencyStart; ulFrequency <= pTSD->FrequencyStop; ulFrequency += pTSD->Bandwidth) {
bSucceeded = false;
for (int nOffsetPos = 0; nOffsetPos < nOffset && !bSucceeded; nOffsetPos++) {
pTun->SetFrequency (ulFrequency + lOffsets[nOffsetPos]);
Sleep (200);
if (SUCCEEDED (pTun->GetStats (bPresent, bLocked, lStrength, lQuality)) && bPresent) {
::SendMessage (pTSD->Hwnd, WM_TUNER_STATS, lStrength, lQuality);
pTun->Scan (ulFrequency + lOffsets[nOffsetPos], pTSD->Hwnd);
bSucceeded = true;
}
}
nProgress = MulDiv(ulFrequency-pTSD->FrequencyStart, 100, pTSD->FrequencyStop-pTSD->FrequencyStart);
::SendMessage (pTSD->Hwnd, WM_TUNER_SCAN_PROGRESS, nProgress,0);
::SendMessage (pTSD->Hwnd, WM_TUNER_STATS, lStrength, lQuality);
if (m_bStopTunerScan) {
break;
}
}
::SendMessage (pTSD->Hwnd, WM_TUNER_SCAN_END, 0, 0);
}
}
}
// msn
void CMainFrame::SendNowPlayingToMSN()
{
if(!AfxGetAppSettings().fNotifyMSN) {
return;
}
CString title, author;
if(m_iMediaLoadState == MLS_LOADED) {
m_wndInfoBar.GetLine(ResStr(IDS_INFOBAR_TITLE), title);
m_wndInfoBar.GetLine(ResStr(IDS_INFOBAR_AUTHOR), author);
if(title.IsEmpty()) {
CPlaylistItem pli;
m_wndPlaylistBar.GetCur(pli);
if(!pli.m_fns.IsEmpty()) {
CString label = !pli.m_label.IsEmpty() ? pli.m_label : pli.m_fns.GetHead();
if(GetPlaybackMode() == PM_FILE) {
CString fn = label;
if(fn.Find(_T("://")) >= 0) {
int i = fn.Find('?');
if(i >= 0) {
fn = fn.Left(i);
}
}
CPath path(fn);
path.StripPath();
path.MakePretty();
path.RemoveExtension();
title = (LPCTSTR)path;
author.Empty();
} else if(GetPlaybackMode() == PM_CAPTURE) {
title = label != pli.m_fns.GetHead() ? label : _T("Live");
author.Empty();
} else if(GetPlaybackMode() == PM_DVD) {
title = _T("DVD");
author.Empty();
}
}
}
}
CStringW buff;
buff += L"\\0Music\\0";
buff += title.IsEmpty() ? L"0" : L"1";
buff += L"\\0";
buff += author.IsEmpty() ? L"{0}" : L"{0} - {1}";
buff += L"\\0";
if(!author.IsEmpty()) {
buff += CStringW(author) + L"\\0";
}
buff += CStringW(title) + L"\\0";
buff += L"\\0\\0";
COPYDATASTRUCT data;
data.dwData = 0x0547;
data.lpData = (PVOID)(LPCWSTR)buff;
data.cbData = buff.GetLength() * 2 + 2;
HWND hWnd = ::FindWindowEx(NULL, NULL, _T("MsnMsgrUIManager"), NULL);
while(hWnd) {
::SendMessage(hWnd, WM_COPYDATA, (WPARAM)NULL, (LPARAM)&data);
hWnd = ::FindWindowEx(NULL, hWnd, _T("MsnMsgrUIManager"), NULL);
}
}
// mIRC
void CMainFrame::SendNowPlayingTomIRC()
{
if(!AfxGetAppSettings().fNotifyGTSdll) {
return;
}
for(int i = 0; i < 20; i++) {
HANDLE hFMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 1024, _T("mIRC"));
if(!hFMap) {
return;
}
if(GetLastError() == ERROR_ALREADY_EXISTS) {
CloseHandle(hFMap);
Sleep(50);
continue;
}
if(LPVOID lpMappingAddress = MapViewOfFile(hFMap, FILE_MAP_WRITE, 0, 0, 0)) {
LPCSTR cmd = m_fAudioOnly ? "/.timerAUDGTS 1 5 mpcaud" : "/.timerVIDGTS 1 5 mpcvid";
strcpy((char*)lpMappingAddress, cmd);
if(HWND hWnd = ::FindWindow(_T("mIRC"), NULL)) {
::SendMessage(hWnd, (WM_USER + 200), (WPARAM)1, (LPARAM)0);
}
UnmapViewOfFile(lpMappingAddress);
}
CloseHandle(hFMap);
break;
}
}
// dynamic menus
void CMainFrame::SetupOpenCDSubMenu()
{
CMenu* pSub = &m_opencds;
if(!IsMenu(pSub->m_hMenu)) {
pSub->CreatePopupMenu();
} else while(pSub->RemoveMenu(0, MF_BYPOSITION)) {
;
}
if(m_iMediaLoadState == MLS_LOADING) {
return;
}
if(AfxGetAppSettings().fHideCDROMsSubMenu) {
return;
}
UINT id = ID_FILE_OPEN_CD_START;
for(TCHAR drive = 'C'; drive <= 'Z'; drive++) {
CString label = GetDriveLabel(drive), str;
CAtlList files;
switch(GetCDROMType(drive, files)) {
case CDROM_Audio:
if(label.IsEmpty()) {
label = _T("Audio CD");
}
str.Format(_T("%s (%c:)"), label, drive);
break;
case CDROM_VideoCD:
if(label.IsEmpty()) {
label = _T("(S)VCD");
}
str.Format(_T("%s (%c:)"), label, drive);
break;
case CDROM_DVDVideo:
if(label.IsEmpty()) {
label = _T("DVD Video");
}
str.Format(_T("%s (%c:)"), label, drive);
break;
default:
break;
}
if(!str.IsEmpty()) {
pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, str);
}
}
}
void CMainFrame::SetupFiltersSubMenu()
{
CMenu* pSub = &m_filters;
if(!IsMenu(pSub->m_hMenu)) {
pSub->CreatePopupMenu();
} else while(pSub->RemoveMenu(0, MF_BYPOSITION)) {
;
}
m_filterpopups.RemoveAll();
m_pparray.RemoveAll();
m_ssarray.RemoveAll();
if(m_iMediaLoadState == MLS_LOADED) {
UINT idf = 0;
UINT ids = ID_FILTERS_SUBITEM_START;
UINT idl = ID_FILTERSTREAMS_SUBITEM_START;
BeginEnumFilters(pGB, pEF, pBF) {
CString name(GetFilterName(pBF));
if(name.GetLength() >= 43) {
name = name.Left(40) + _T("...");
}
CLSID clsid = GetCLSID(pBF);
if(clsid == CLSID_AVIDec) {
CComPtr pPin = GetFirstPin(pBF);
AM_MEDIA_TYPE mt;
if(pPin && SUCCEEDED(pPin->ConnectionMediaType(&mt))) {
DWORD c = ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biCompression;
switch(c) {
case BI_RGB:
name += _T(" (RGB)");
break;
case BI_RLE4:
name += _T(" (RLE4)");
break;
case BI_RLE8:
name += _T(" (RLE8)");
break;
case BI_BITFIELDS:
name += _T(" (BITF)");
break;
default:
name.Format(_T("%s (%c%c%c%c)"),
CString(name), (TCHAR)((c>>0)&0xff), (TCHAR)((c>>8)&0xff), (TCHAR)((c>>16)&0xff), (TCHAR)((c>>24)&0xff));
break;
}
}
} else if(clsid == CLSID_ACMWrapper) {
CComPtr pPin = GetFirstPin(pBF);
AM_MEDIA_TYPE mt;
if(pPin && SUCCEEDED(pPin->ConnectionMediaType(&mt))) {
WORD c = ((WAVEFORMATEX*)mt.pbFormat)->wFormatTag;
name.Format(_T("%s (0x%04x)"), CString(name), (int)c);
}
} else if(clsid == __uuidof(CTextPassThruFilter) || clsid == __uuidof(CNullTextRenderer)
|| clsid == GUIDFromCString(_T("{48025243-2D39-11CE-875D-00608CB78066}"))) { // ISCR
// hide these
continue;
}
CAutoPtr pSubSub(DNew CMenu);
pSubSub->CreatePopupMenu();
int nPPages = 0;
CComQIPtr pSPP = pBF;
/* if(pSPP)
{
CAUUID caGUID;
caGUID.pElems = NULL;
if(SUCCEEDED(pSPP->GetPages(&caGUID)) && caGUID.cElems > 0)
{
*/
m_pparray.Add(pBF);
pSubSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, ids, ResStr(IDS_MAINFRM_116));
/*
if(caGUID.pElems) CoTaskMemFree(caGUID.pElems);
*/
nPPages++;
/* }
}
*/
BeginEnumPins(pBF, pEP, pPin) {
CString name = GetPinName(pPin);
name.Replace(_T("&"), _T("&&"));
if(pSPP = pPin) {
CAUUID caGUID;
caGUID.pElems = NULL;
if(SUCCEEDED(pSPP->GetPages(&caGUID)) && caGUID.cElems > 0) {
m_pparray.Add(pPin);
pSubSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, ids+nPPages, name + ResStr(IDS_MAINFRM_117));
if(caGUID.pElems) {
CoTaskMemFree(caGUID.pElems);
}
nPPages++;
}
}
}
EndEnumPins;
CComQIPtr pSS = pBF;
if(pSS) {
DWORD nStreams = 0;
DWORD flags = (DWORD)-1;
DWORD group = (DWORD)-1;
DWORD prevgroup = (DWORD)-1;
LCID lcid;
WCHAR* wname = NULL;
CComPtr pObj, pUnk;
pSS->Count(&nStreams);
if(nStreams > 0 && nPPages > 0) {
pSubSub->AppendMenu(MF_SEPARATOR|MF_ENABLED);
}
UINT idlstart = idl;
for(DWORD i = 0; i < nStreams; i++, pObj = NULL, pUnk = NULL) {
m_ssarray.Add(pSS);
flags = group = 0;
wname = NULL;
pSS->Info(i, NULL, &flags, &lcid, &group, &wname, &pObj, &pUnk);
if(group != prevgroup && idl > idlstart) {
pSubSub->AppendMenu(MF_SEPARATOR|MF_ENABLED);
}
prevgroup = group;
if(flags & AMSTREAMSELECTINFO_EXCLUSIVE) {
} else if(flags & AMSTREAMSELECTINFO_ENABLED) {
}
if(!wname) {
CStringW stream(ResStr(IDS_AG_UNKNOWN_STREAM));
wname = (WCHAR*)CoTaskMemAlloc((stream.GetLength()+3+1)*sizeof(WCHAR));
swprintf(wname, L"%s %d", stream, min(i+1,999));
}
CString name(wname);
name.Replace(_T("&"), _T("&&"));
pSubSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, idl++, name);
CoTaskMemFree(wname);
}
if(nStreams == 0) {
pSS.Release();
}
}
if(nPPages == 1 && !pSS) {
pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, ids, name);
} else {
pSub->AppendMenu(MF_BYPOSITION|MF_STRING|MF_DISABLED|MF_GRAYED, idf, name);
if(nPPages > 0 || pSS) {
MENUITEMINFO mii;
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_STATE|MIIM_SUBMENU;
mii.fType = MF_POPUP;
mii.hSubMenu = pSubSub->m_hMenu;
mii.fState = (pSPP || pSS) ? MF_ENABLED : (MF_DISABLED|MF_GRAYED);
pSub->SetMenuItemInfo(idf, &mii, TRUE);
m_filterpopups.Add(pSubSub);
}
}
ids += nPPages;
idf++;
}
EndEnumFilters;
}
}
void CMainFrame::SetupAudioSwitcherSubMenu()
{
CMenu* pSub = &m_audios;
if(!IsMenu(pSub->m_hMenu)) {
pSub->CreatePopupMenu();
} else while(pSub->RemoveMenu(0, MF_BYPOSITION)) {
;
}
if(m_iMediaLoadState == MLS_LOADED) {
UINT id = ID_AUDIO_SUBITEM_START;
CComQIPtr pSS = FindFilter(__uuidof(CAudioSwitcherFilter), pGB);
if(!pSS) {
pSS = FindFilter(L"{D3CD7858-971A-4838-ACEC-40CA5D529DC8}", pGB);
}
if(pSS) {
DWORD cStreams = 0;
if(SUCCEEDED(pSS->Count(&cStreams)) && cStreams > 0) {
pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, ResStr(IDS_SUBTITLES_OPTIONS));
pSub->AppendMenu(MF_SEPARATOR|MF_ENABLED);
for(int i = 0; i < (int)cStreams; i++) {
WCHAR* pName = NULL;
POSITION idx = m_iAudioStreams.FindIndex(i);
int iStream = m_iAudioStreams.GetAt(idx);
if(FAILED(pSS->Info(iStream, NULL, NULL, NULL, NULL, &pName, NULL, NULL))) { // audio streams are reordered, so find the index from the initial order
break;
}
CString name(pName);
name.Replace(_T("&"), _T("&&"));
pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, name);
CoTaskMemFree(pName);
}
}
}
}
}
void CMainFrame::SetupSubtitlesSubMenu()
{
CMenu* pSub = &m_subtitles;
if(!IsMenu(pSub->m_hMenu)) {
pSub->CreatePopupMenu();
} else while(pSub->RemoveMenu(0, MF_BYPOSITION)) {
;
}
if(m_iMediaLoadState != MLS_LOADED || m_fAudioOnly || !m_pCAP) {
return;
}
UINT id = ID_SUBTITLES_SUBITEM_START;
POSITION pos = m_pSubStreams.GetHeadPosition();
if(pos) {
pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, ResStr(IDS_SUBTITLES_OPTIONS));
pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, ResStr(IDS_SUBTITLES_STYLES));
pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, ResStr(IDS_SUBTITLES_RELOAD));
pSub->AppendMenu(MF_SEPARATOR);
pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, ResStr(IDS_SUBTITLES_ENABLE));
pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, ResStr(IDS_SUBTITLES_DEFAULT_STYLE));
pSub->AppendMenu(MF_SEPARATOR);
}
while(pos) {
CComPtr pSubStream = m_pSubStreams.GetNext(pos);
if(!pSubStream) {
continue;
}
for(int i = 0, j = pSubStream->GetStreamCount(); i < j; i++) {
WCHAR* pName = NULL;
if(SUCCEEDED(pSubStream->GetStreamInfo(i, &pName, NULL))) {
CString name(pName);
name.Replace(_T("&"), _T("&&"));
pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, name);
CoTaskMemFree(pName);
} else {
pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, ResStr(IDS_AG_UNKNOWN));
}
}
// TODO: find a better way to group these entries
if(pos && m_pSubStreams.GetAt(pos)) {
CLSID cur, next;
pSubStream->GetClassID(&cur);
m_pSubStreams.GetAt(pos)->GetClassID(&next);
if(cur != next) {
pSub->AppendMenu(MF_SEPARATOR);
}
}
}
}
void CMainFrame::SetupNavAudioSubMenu()
{
CMenu* pSub = &m_navaudio;
if(!IsMenu(pSub->m_hMenu)) {
pSub->CreatePopupMenu();
} else while(pSub->RemoveMenu(0, MF_BYPOSITION)) {
;
}
if(m_iMediaLoadState != MLS_LOADED) {
return;
}
UINT id = ID_NAVIGATE_AUDIO_SUBITEM_START;
if(GetPlaybackMode() == PM_FILE || (GetPlaybackMode() == PM_CAPTURE && AfxGetAppSettings().iDefaultCaptureDevice == 1)) {
SetupNavStreamSelectSubMenu(pSub, id, 1);
} else if(GetPlaybackMode() == PM_DVD) {
ULONG ulStreamsAvailable, ulCurrentStream;
if(FAILED(pDVDI->GetCurrentAudio(&ulStreamsAvailable, &ulCurrentStream))) {
return;
}
LCID DefLanguage;
DVD_AUDIO_LANG_EXT ext;
if(FAILED(pDVDI->GetDefaultAudioLanguage(&DefLanguage, &ext))) {
return;
}
for(ULONG i = 0; i < ulStreamsAvailable; i++) {
LCID Language;
if(FAILED(pDVDI->GetAudioLanguage(i, &Language))) {
continue;
}
UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
if(Language == DefLanguage) {
flags |= MF_DEFAULT;
}
if(i == ulCurrentStream) {
flags |= MF_CHECKED;
}
CString str(ResStr(IDS_AG_UNKNOWN));
if(Language) {
int len = GetLocaleInfo(Language, LOCALE_SENGLANGUAGE, str.GetBuffer(256), 256);
str.ReleaseBufferSetLength(max(len-1, 0));
}
DVD_AudioAttributes ATR;
if(SUCCEEDED(pDVDI->GetAudioAttributes(i, &ATR))) {
switch(ATR.LanguageExtension) {
case DVD_AUD_EXT_NotSpecified:
default:
break;
case DVD_AUD_EXT_Captions:
str += _T(" (Captions)");
break;
case DVD_AUD_EXT_VisuallyImpaired:
str += _T(" (Visually Impaired)");
break;
case DVD_AUD_EXT_DirectorComments1:
str += ResStr(IDS_MAINFRM_121);
break;
case DVD_AUD_EXT_DirectorComments2:
str += ResStr(IDS_MAINFRM_122);
break;
}
CString format = GetDVDAudioFormatName(ATR);
if(!format.IsEmpty()) {
str.Format(ResStr(IDS_MAINFRM_11),
CString(str),
format,
ATR.dwFrequency,
ATR.bQuantization,
ATR.bNumberOfChannels,
(ATR.bNumberOfChannels > 1 ? ResStr(IDS_MAINFRM_13) : ResStr(IDS_MAINFRM_12)));
}
}
str.Replace(_T("&"), _T("&&"));
pSub->AppendMenu(flags, id++, str);
}
}
}
void CMainFrame::SetupNavSubtitleSubMenu()
{
CMenu* pSub = &m_navsubtitle;
if(!IsMenu(pSub->m_hMenu)) {
pSub->CreatePopupMenu();
} else while(pSub->RemoveMenu(0, MF_BYPOSITION)) {
;
}
if(m_iMediaLoadState != MLS_LOADED) {
return;
}
UINT id = ID_NAVIGATE_SUBP_SUBITEM_START;
if(GetPlaybackMode() == PM_FILE || (GetPlaybackMode() == PM_CAPTURE && AfxGetAppSettings().iDefaultCaptureDevice == 1)) {
SetupNavStreamSelectSubMenu(pSub, id, 2);
} else if(GetPlaybackMode() == PM_DVD) {
ULONG ulStreamsAvailable, ulCurrentStream;
BOOL bIsDisabled;
if(FAILED(pDVDI->GetCurrentSubpicture(&ulStreamsAvailable, &ulCurrentStream, &bIsDisabled))
|| ulStreamsAvailable == 0) {
return;
}
LCID DefLanguage;
DVD_SUBPICTURE_LANG_EXT ext;
if(FAILED(pDVDI->GetDefaultSubpictureLanguage(&DefLanguage, &ext))) {
return;
}
pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|(bIsDisabled?0:MF_CHECKED), id++, ResStr(IDS_AG_ENABLED));
pSub->AppendMenu(MF_BYCOMMAND|MF_SEPARATOR|MF_ENABLED);
for(ULONG i = 0; i < ulStreamsAvailable; i++) {
LCID Language;
if(FAILED(pDVDI->GetSubpictureLanguage(i, &Language))) {
continue;
}
UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
if(Language == DefLanguage) {
flags |= MF_DEFAULT;
}
if(i == ulCurrentStream) {
flags |= MF_CHECKED;
}
CString str(ResStr(IDS_AG_UNKNOWN));
if(Language) {
int len = GetLocaleInfo(Language, LOCALE_SENGLANGUAGE, str.GetBuffer(256), 256);
str.ReleaseBufferSetLength(max(len-1, 0));
}
DVD_SubpictureAttributes ATR;
if(SUCCEEDED(pDVDI->GetSubpictureAttributes(i, &ATR))) {
switch(ATR.LanguageExtension) {
case DVD_SP_EXT_NotSpecified:
default:
break;
case DVD_SP_EXT_Caption_Normal:
str += _T("");
break;
case DVD_SP_EXT_Caption_Big:
str += _T(" (Big)");
break;
case DVD_SP_EXT_Caption_Children:
str += _T(" (Children)");
break;
case DVD_SP_EXT_CC_Normal:
str += _T(" (CC)");
break;
case DVD_SP_EXT_CC_Big:
str += _T(" (CC Big)");
break;
case DVD_SP_EXT_CC_Children:
str += _T(" (CC Children)");
break;
case DVD_SP_EXT_Forced:
str += _T(" (Forced)");
break;
case DVD_SP_EXT_DirectorComments_Normal:
str += _T(" (Director Comments)");
break;
case DVD_SP_EXT_DirectorComments_Big:
str += _T(" (Director Comments, Big)");
break;
case DVD_SP_EXT_DirectorComments_Children:
str += _T(" (Director Comments, Children)");
break;
}
}
str.Replace(_T("&"), _T("&&"));
pSub->AppendMenu(flags, id++, str);
}
}
}
void CMainFrame::SetupNavAngleSubMenu()
{
CMenu* pSub = &m_navangle;
if(!IsMenu(pSub->m_hMenu)) {
pSub->CreatePopupMenu();
} else while(pSub->RemoveMenu(0, MF_BYPOSITION)) {
;
}
if(m_iMediaLoadState != MLS_LOADED) {
return;
}
UINT id = ID_NAVIGATE_ANGLE_SUBITEM_START;
if(GetPlaybackMode() == PM_FILE) {
SetupNavStreamSelectSubMenu(pSub, id, 0);
} else if(GetPlaybackMode() == PM_DVD) {
ULONG ulStreamsAvailable, ulCurrentStream;
if(FAILED(pDVDI->GetCurrentAngle(&ulStreamsAvailable, &ulCurrentStream))) {
return;
}
if(ulStreamsAvailable < 2) {
return; // one choice is not a choice...
}
for(ULONG i = 1; i <= ulStreamsAvailable; i++) {
UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
if(i == ulCurrentStream) {
flags |= MF_CHECKED;
}
CString str;
str.Format(ResStr(IDS_AG_ANGLE), i);
pSub->AppendMenu(flags, id++, str);
}
}
}
void CMainFrame::SetupNavChaptersSubMenu()
{
CMenu* pSub = &m_navchapters;
if(!IsMenu(pSub->m_hMenu)) {
pSub->CreatePopupMenu();
} else while(pSub->RemoveMenu(0, MF_BYPOSITION)) {
;
}
if(m_iMediaLoadState != MLS_LOADED) {
return;
}
UINT id = ID_NAVIGATE_CHAP_SUBITEM_START;
if(GetPlaybackMode() == PM_FILE) {
SetupChapters();
REFERENCE_TIME rt = GetPos();
DWORD j = m_pCB->ChapLookup(&rt, NULL);
for(DWORD i = 0; i < m_pCB->ChapGetCount(); i++, id++) {
rt = 0;
CComBSTR bstr;
if(FAILED(m_pCB->ChapGet(i, &rt, &bstr))) {
continue;
}
int s = (int)((rt/10000000)%60);
int m = (int)((rt/10000000/60)%60);
int h = (int)((rt/10000000/60/60));
CString time;
time.Format(_T("[%02d:%02d:%02d] "), h, m, s);
CString name = CString(bstr);
name.Replace(_T("&"), _T("&&"));
name.Replace(_T("\t"), _T(" "));
UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
if(i == j) {
flags |= MF_CHECKED;
}
if(id != ID_NAVIGATE_CHAP_SUBITEM_START && i == 0) {
pSub->AppendMenu(MF_SEPARATOR);
}
pSub->AppendMenu(flags, id, name + '\t' + time);
}
if(m_wndPlaylistBar.GetCount() > 1) {
POSITION pos = m_wndPlaylistBar.m_pl.GetHeadPosition();
while(pos) {
UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
if(pos == m_wndPlaylistBar.m_pl.GetPos()) {
flags |= MF_CHECKED;
}
if(id != ID_NAVIGATE_CHAP_SUBITEM_START && pos == m_wndPlaylistBar.m_pl.GetHeadPosition()) {
pSub->AppendMenu(MF_SEPARATOR);
}
CPlaylistItem& pli = m_wndPlaylistBar.m_pl.GetNext(pos);
CString name = pli.GetLabel();
name.Replace(_T("&"), _T("&&"));
pSub->AppendMenu(flags, id++, name);
}
}
} else if(GetPlaybackMode() == PM_DVD) {
ULONG ulNumOfVolumes, ulVolume;
DVD_DISC_SIDE Side;
ULONG ulNumOfTitles = 0;
pDVDI->GetDVDVolumeInfo(&ulNumOfVolumes, &ulVolume, &Side, &ulNumOfTitles);
DVD_PLAYBACK_LOCATION2 Location;
pDVDI->GetCurrentLocation(&Location);
ULONG ulNumOfChapters = 0;
pDVDI->GetNumberOfChapters(Location.TitleNum, &ulNumOfChapters);
ULONG ulUOPs = 0;
pDVDI->GetCurrentUOPS(&ulUOPs);
for(ULONG i = 1; i <= ulNumOfTitles; i++) {
UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
if(i == Location.TitleNum) {
flags |= MF_CHECKED;
}
if(ulUOPs&UOP_FLAG_Play_Title) {
flags |= MF_DISABLED|MF_GRAYED;
}
CString str;
str.Format(ResStr(IDS_AG_TITLE), i);
pSub->AppendMenu(flags, id++, str);
}
for(ULONG i = 1; i <= ulNumOfChapters; i++) {
UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
if(i == Location.ChapterNum) {
flags |= MF_CHECKED;
}
if(ulUOPs&UOP_FLAG_Play_Chapter) {
flags |= MF_DISABLED|MF_GRAYED;
}
if(i == 1) {
flags |= MF_MENUBARBREAK;
}
CString str;
str.Format(ResStr(IDS_AG_CHAPTER), i);
pSub->AppendMenu(flags, id++, str);
}
} else if(GetPlaybackMode() == PM_CAPTURE && AfxGetAppSettings().iDefaultCaptureDevice == 1) {
AppSettings& s = AfxGetAppSettings();
POSITION pos = s.m_DVBChannels.GetHeadPosition();
while (pos) {
CDVBChannel& Channel = s.m_DVBChannels.GetNext(pos);
UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
if (Channel.GetPrefNumber() == s.nDVBLastChannel) {
flags |= MF_CHECKED;
}
pSub->AppendMenu(flags, ID_NAVIGATE_CHAP_SUBITEM_START + Channel.GetPrefNumber(), Channel.GetName());
}
}
}
IBaseFilter* CMainFrame::FindSourceSelectableFilter()
{
IBaseFilter* pSF = NULL;
pSF = FindFilter(CLSID_OggSplitter, pGB);
if(!pSF) {
pSF = FindFilter(L"{171252A0-8820-4AFE-9DF8-5C92B2D66B04}", pGB); // LAV Splitter
}
if(!pSF) {
pSF = FindFilter(L"{B98D13E7-55DB-4385-A33D-09FD1BA26338}", pGB); // LAV Splitter Source
}
if(!pSF) {
pSF = FindFilter(L"{55DA30FC-F16B-49fc-BAA5-AE59FC65F82D}", pGB);
}
if(!pSF) {
pSF = FindFilter(L"{529A00DB-0C43-4f5b-8EF2-05004CBE0C6F}", pGB); // AV Splitter
}
if(!pSF) {
pSF = FindFilter(L"{D8980E15-E1F6-4916-A10F-D7EB4E9E10B8}", pGB); // AV Source
}
if(!pSF) {
pSF = FindFilter(__uuidof(CMpegSplitterFilter), pGB);
}
if(!pSF) {
pSF = FindFilter(__uuidof(CMpegSourceFilter), pGB);
}
return pSF;
}
void CMainFrame::SetupNavStreamSelectSubMenu(CMenu* pSub, UINT id, DWORD dwSelGroup)
{
UINT baseid = id;
CComQIPtr pSS = FindSourceSelectableFilter();
if (!pSS) {
pSS = pGB;
}
if(!pSS) {
return;
}
DWORD cStreams;
if(FAILED(pSS->Count(&cStreams))) {
return;
}
DWORD dwPrevGroup = (DWORD)-1;
for(int i = 0, j = cStreams; i < j; i++) {
DWORD dwFlags, dwGroup;
LCID lcid;
WCHAR* pszName = NULL;
if(FAILED(pSS->Info(i, NULL, &dwFlags, &lcid, &dwGroup, &pszName, NULL, NULL))
|| !pszName) {
continue;
}
CString name(pszName);
CString lcname = CString(name).MakeLower();
if(pszName) {
CoTaskMemFree(pszName);
}
if(dwGroup != dwSelGroup) {
continue;
}
if(dwPrevGroup != -1 && dwPrevGroup != dwGroup) {
pSub->AppendMenu(MF_SEPARATOR);
}
dwPrevGroup = dwGroup;
CString str;
if(lcname.Find(_T(" off")) >= 0) {
str = ResStr(IDS_AG_DISABLED);
} else {
if(lcid == 0) {
str.Format(ResStr(IDS_AG_UNKNOWN), id - baseid);
} else {
int len = GetLocaleInfo(lcid, LOCALE_SENGLANGUAGE, str.GetBuffer(64), 64);
str.ReleaseBufferSetLength(max(len-1, 0));
}
CString lcstr = CString(str).MakeLower();
if(str.IsEmpty() || lcname.Find(lcstr) >= 0) {
str = name;
} else if(!name.IsEmpty()) {
str = CString(name) + _T(" (") + str + _T(")");
}
}
UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
if(dwFlags) {
flags |= MF_CHECKED;
}
str.Replace(_T("&"), _T("&&"));
pSub->AppendMenu(flags, id++, str);
}
}
void CMainFrame::OnNavStreamSelectSubMenu(UINT id, DWORD dwSelGroup)
{
CComQIPtr pSS = FindSourceSelectableFilter();
if (!pSS) {
pSS = pGB;
}
if(!pSS) {
return;
}
DWORD cStreams;
if(FAILED(pSS->Count(&cStreams))) {
return;
}
for(int i = 0, j = cStreams; i < j; i++) {
DWORD dwFlags, dwGroup;
LCID lcid;
WCHAR* pszName = NULL;
if(FAILED(pSS->Info(i, NULL, &dwFlags, &lcid, &dwGroup, &pszName, NULL, NULL))
|| !pszName) {
continue;
}
if(pszName) {
CoTaskMemFree(pszName);
}
if(dwGroup != dwSelGroup) {
continue;
}
if(id == 0) {
pSS->Enable(i, AMSTREAMSELECTENABLE_ENABLE);
break;
}
id--;
}
}
void CMainFrame::SetupRecentFilesSubMenu()
{
CMenu* pSub = &m_recentfiles;
if(!IsMenu(pSub->m_hMenu)) {
pSub->CreatePopupMenu();
} else while(pSub->RemoveMenu(0, MF_BYPOSITION)) {
;
}
UINT id = ID_RECENT_FILE_START;
CRecentFileList& MRU = AfxGetAppSettings().MRU;
MRU.ReadList();
int mru_count=0;
for(int i = 0; i < MRU.GetSize(); i++) {
if(!MRU[i].IsEmpty()) {
mru_count++;
break;
}
}
if(mru_count) {
pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, ID_RECENT_FILES_CLEAR, ResStr(IDS_RECENT_FILES_CLEAR));
pSub->AppendMenu(MF_SEPARATOR|MF_ENABLED);
}
for(int i = 0; i < MRU.GetSize(); i++) {
UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
if(!MRU[i].IsEmpty()) {
pSub->AppendMenu(flags, id, MRU[i]);
}
id++;
}
}
void CMainFrame::SetupFavoritesSubMenu()
{
CMenu* pSub = &m_favorites;
if(!IsMenu(pSub->m_hMenu)) {
pSub->CreatePopupMenu();
} else while(pSub->RemoveMenu(0, MF_BYPOSITION)) {
;
}
AppSettings& s = AfxGetAppSettings();
pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, ID_FAVORITES_ADD, ResStr(IDS_FAVORITES_ADD));
pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, ID_FAVORITES_ORGANIZE, ResStr(IDS_FAVORITES_ORGANIZE));
int nLastGroupStart = pSub->GetMenuItemCount();
UINT id = ID_FAVORITES_FILE_START;
CAtlList sl;
AfxGetAppSettings().GetFav(FAV_FILE, sl);
POSITION pos = sl.GetHeadPosition();
while(pos) {
UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
CString f_str = sl.GetNext(pos);
f_str.Replace(_T("&"), _T("&&"));
f_str.Replace(_T("\t"), _T(" "));
CAtlList sl;
Explode(f_str, sl, ';', 3);
f_str = sl.RemoveHead();
CString str;
if(!sl.IsEmpty()) {
bool bPositionDataPresent = false;
// pos
REFERENCE_TIME rt = 0;
if(1 == _stscanf_s(sl.GetHead(), _T("%I64d"), &rt) && rt > 0) {
DVD_HMSF_TIMECODE hmsf = RT2HMSF(rt, 0);
str.Format(_T("[%02d:%02d:%02d]"), hmsf.bHours, hmsf.bMinutes, hmsf.bSeconds);
bPositionDataPresent = true;
}
// relative drive
if ( sl.GetCount() > 1 ) { // Here to prevent crash if old favorites settings are present
sl.RemoveHead();
BOOL bRelativeDrive = FALSE;
if ( _stscanf_s(sl.GetHead(), _T("%d"), &bRelativeDrive) == 1 ) {
if(bRelativeDrive) {
str.Format(_T("[RD]%s"), CString(str));
}
}
}
if(!str.IsEmpty()) {
f_str.Format(_T("%s\t%.14s"), CString(f_str), CString(str));
}
}
if(!f_str.IsEmpty()) {
pSub->AppendMenu(flags, id, f_str);
}
id++;
}
if(id > ID_FAVORITES_FILE_START) {
pSub->InsertMenu(nLastGroupStart, MF_SEPARATOR|MF_ENABLED|MF_BYPOSITION);
}
nLastGroupStart = pSub->GetMenuItemCount();
id = ID_FAVORITES_DVD_START;
s.GetFav(FAV_DVD, sl);
pos = sl.GetHeadPosition();
while(pos) {
UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
CString str = sl.GetNext(pos);
str.Replace(_T("&"), _T("&&"));
CAtlList sl;
Explode(str, sl, ';', 2);
str = sl.RemoveHead();
if(!sl.IsEmpty()) {
// TODO
}
if(!str.IsEmpty()) {
pSub->AppendMenu(flags, id, str);
}
id++;
}
if(id > ID_FAVORITES_DVD_START) {
pSub->InsertMenu(nLastGroupStart, MF_SEPARATOR|MF_ENABLED|MF_BYPOSITION);
}
nLastGroupStart = pSub->GetMenuItemCount();
id = ID_FAVORITES_DEVICE_START;
s.GetFav(FAV_DEVICE, sl);
pos = sl.GetHeadPosition();
while(pos) {
UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
CString str = sl.GetNext(pos);
str.Replace(_T("&"), _T("&&"));
CAtlList sl;
Explode(str, sl, ';', 2);
str = sl.RemoveHead();
if(!str.IsEmpty()) {
pSub->AppendMenu(flags, id, str);
}
id++;
}
}
void CMainFrame::SetupShadersSubMenu()
{
CMenu* pSub = &m_shaders;
if(!IsMenu(pSub->m_hMenu)) {
pSub->CreatePopupMenu();
} else while(pSub->RemoveMenu(0, MF_BYPOSITION)) {
;
}
pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, ID_SHADERS_OFF, ResStr(IDS_SHADER_OFF));
if(POSITION pos = AfxGetAppSettings().m_shaders.GetHeadPosition()) {
pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, ID_SHADERS_COMBINE, ResStr(IDS_SHADER_COMBINE));
pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, ID_SHADERS_EDIT, ResStr(IDS_SHADER_EDIT));
pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, ID_SHADER_TOGGLE, ResStr(IDS_SHADER_TOGGLE));
pSub->AppendMenu(MF_SEPARATOR);
pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, ID_SHADERS_OFFSCR, ResStr(IDS_SHADER_OFFSCREENSPACE));
pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, ID_SHADERS_COMBINESCR, ResStr(IDS_SHADER_COMBINESCREENSPACE));
pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, ID_SHADER_TOGGLESCREENSPACE, ResStr(IDS_SHADER_TOGGLESCREENSPACE));
pSub->AppendMenu(MF_SEPARATOR);
UINT id = ID_SHADERS_DYNAMIC;
MENUITEMINFO mii;
memset(&mii, 0, sizeof(mii));
mii.cbSize = sizeof(mii);
mii.fMask |= MIIM_DATA;
while(pos) {
const AppSettings::Shader& s = AfxGetAppSettings().m_shaders.GetNext(pos);
CString label = s.label;
label.Replace(_T("&"), _T("&&"));
pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id, label);
mii.dwItemData = (ULONG_PTR)&s;
pSub->SetMenuItemInfo(id, &mii);
id++;
}
}
}
/////////////
void CMainFrame::ShowControls(int nCS, bool fSave)
{
int nCSprev = AfxGetAppSettings().nCS;
int hbefore = 0, hafter = 0;
m_pLastBar = NULL;
POSITION pos = m_bars.GetHeadPosition();
for(int i = 1; pos; i <<= 1) {
CControlBar* pNext = m_bars.GetNext(pos);
ShowControlBar(pNext, !!(nCS&i), TRUE);
if(nCS&i) {
m_pLastBar = pNext;
}
CSize s = pNext->CalcFixedLayout(FALSE, TRUE);
if(nCSprev&i) {
hbefore += s.cy;
}
if(nCS&i) {
hafter += s.cy;
}
}
WINDOWPLACEMENT wp;
wp.length = sizeof(wp);
GetWindowPlacement(&wp);
if(wp.showCmd != SW_SHOWMAXIMIZED && !m_fFullScreen) {
CRect r;
GetWindowRect(r);
MoveWindow(r.left, r.top, r.Width(), r.Height()+(hafter-hbefore));
}
if(fSave) {
AfxGetAppSettings().nCS = nCS;
}
RecalcLayout();
}
void CMainFrame::SetAlwaysOnTop(int i)
{
AfxGetAppSettings().iOnTop = i;
if(!m_fFullScreen) {
const CWnd* pInsertAfter = NULL;
if(i == 0) {
pInsertAfter = &wndNoTopMost;
} else if(i == 1) {
pInsertAfter = &wndTopMost;
} else { // if(i == 2)
pInsertAfter = GetMediaState() == State_Running ? &wndTopMost : &wndNoTopMost;
}
SetWindowPos(pInsertAfter, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
} else if(!(GetWindowLong(m_hWnd, GWL_EXSTYLE)&WS_EX_TOPMOST)) {
if (!AfxGetAppSettings().IsD3DFullscreen()) {
SetWindowPos(&wndTopMost, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
}
}
}
// foxX: as with audio streams, this one will tell if a subtitle comes before the other,
// in accordance with user options regarding subtitle language order
bool DoesSubPrecede(const CComPtr &a, const CComPtr &b)
{
WCHAR *pName;
if(!SUCCEEDED(a->GetStreamInfo(0, &pName, NULL))) {
return false;
}
CStringW nameA(pName);
CoTaskMemFree(pName);
if(!SUCCEEDED(b->GetStreamInfo(0, &pName, NULL))) {
return false;
}
CStringW nameB(pName);
CoTaskMemFree(pName);
int ia = -1;
int ib = -1;
CStringW slo = AfxGetAppSettings().strSubtitlesLanguageOrder;
int tPos = 0;
CStringW lang = slo.Tokenize(_T(",; "), tPos);
while(tPos != -1 && ia == -1 && ib == -1) {
int ll = lang.GetLength();
if(nameA.Left(ll).CompareNoCase(lang) == 0) {
ia = tPos;
}
if(nameB.Left(ll).CompareNoCase(lang) == 0) {
ib = tPos;
}
lang = slo.Tokenize(_T(",; "), tPos);
}
if(ia != -1 && ib == -1) {
return true;
}
return false;
}
// foxX: inserts the subtitle stream exactly where it should be, base on user preference
ISubStream *InsertSubStream(CInterfaceList *subStreams, const CComPtr &theSubStream)
{
POSITION pos = subStreams->GetHeadPosition();
POSITION newPos = NULL;
bool processed = false;
while(!processed && pos) {
POSITION prevPos = pos;
CComPtr pSubStream = subStreams->GetNext(pos);
if(DoesSubPrecede(theSubStream, pSubStream)) {
if(prevPos == subStreams->GetHeadPosition()) {
newPos = subStreams->AddHead(theSubStream);
} else {
newPos = subStreams->InsertBefore(prevPos, theSubStream);
}
processed = true;
}
}
if(!processed) {
newPos = subStreams->AddTail(theSubStream);
}
if(newPos == NULL) {
newPos = subStreams->GetTailPosition();
}
if(newPos == NULL) {
return NULL;
}
return subStreams->GetAt(newPos);
}
void CMainFrame::AddTextPassThruFilter()
{
BeginEnumFilters(pGB, pEF, pBF) {
if(!IsSplitter(pBF)) {
continue;
}
BeginEnumPins(pBF, pEP, pPin) {
CComPtr pPinTo;
AM_MEDIA_TYPE mt;
if(FAILED(pPin->ConnectedTo(&pPinTo)) || !pPinTo
|| FAILED(pPin->ConnectionMediaType(&mt))
|| mt.majortype != MEDIATYPE_Text && mt.majortype != MEDIATYPE_Subtitle) {
continue;
}
CComQIPtr pTPTF = DNew CTextPassThruFilter(this);
CStringW name;
name.Format(L"TextPassThru%08x", pTPTF);
if(FAILED(pGB->AddFilter(pTPTF, name))) {
continue;
}
HRESULT hr;
hr = pPinTo->Disconnect();
hr = pPin->Disconnect();
if(FAILED(hr = pGB->ConnectDirect(pPin, GetFirstPin(pTPTF, PINDIR_INPUT), NULL))
|| FAILED(hr = pGB->ConnectDirect(GetFirstPin(pTPTF, PINDIR_OUTPUT), pPinTo, NULL))) {
hr = pGB->ConnectDirect(pPin, pPinTo, NULL);
} else {
InsertSubStream(&m_pSubStreams, CComQIPtr(pTPTF));
}
}
EndEnumPins;
}
EndEnumFilters;
}
bool CMainFrame::LoadSubtitle(CString fn, ISubStream **actualStream)
{
CComPtr pSubStream;
// TMP: maybe this will catch something for those who get a runtime error dialog when opening subtitles from cds
try {
if(!pSubStream) {
CAutoPtr pVSF(DNew CVobSubFile(&m_csSubLock));
if(CString(CPath(fn).GetExtension()).MakeLower() == _T(".idx") && pVSF && pVSF->Open(fn) && pVSF->GetStreamCount() > 0) {
pSubStream = pVSF.Detach();
}
}
if(!pSubStream) {
CAutoPtr pRTS(DNew CRenderedTextSubtitle(&m_csSubLock, &AfxGetAppSettings().subdefstyle, AfxGetAppSettings().fUseDefaultSubtitlesStyle));
if(pRTS && pRTS->Open(fn, DEFAULT_CHARSET) && pRTS->GetStreamCount() > 0) {
pSubStream = pRTS.Detach();
}
}
} catch(CException* e) {
e->Delete();
}
if(pSubStream) {
//m_pSubStreams.AddTail(pSubStream);
ISubStream *r = InsertSubStream(&m_pSubStreams, pSubStream);
if(actualStream != NULL) {
*actualStream = r;
}
}
return(!!pSubStream);
}
void CMainFrame::UpdateSubtitle(bool fDisplayMessage, bool fApplyDefStyle)
{
if(!m_pCAP) {
return;
}
int i = m_iSubtitleSel;
POSITION pos = m_pSubStreams.GetHeadPosition();
while(pos && i >= 0) {
CComPtr pSubStream = m_pSubStreams.GetNext(pos);
if(i < pSubStream->GetStreamCount()) {
CAutoLock cAutoLock(&m_csSubLock);
pSubStream->SetStream(i);
SetSubtitle(pSubStream, fApplyDefStyle);
if (fDisplayMessage) {
WCHAR* pName = NULL;
if(SUCCEEDED(pSubStream->GetStreamInfo(0, &pName, NULL))) {
CString strMessage;
strMessage.Format(ResStr(IDS_MAINFRM_45), pName, _T(""));
m_OSD.DisplayMessage (OSD_TOPLEFT, strMessage);
}
}
return;
}
i -= pSubStream->GetStreamCount();
}
if (fDisplayMessage && m_iSubtitleSel < 0) {
m_OSD.DisplayMessage (OSD_TOPLEFT, ResStr(IDS_MAINFRM_44));
}
m_pCAP->SetSubPicProvider(NULL);
}
void CMainFrame::SetSubtitle(ISubStream* pSubStream, bool fApplyDefStyle)
{
AppSettings& s = AfxGetAppSettings();
if(pSubStream) {
CLSID clsid;
pSubStream->GetClassID(&clsid);
if(clsid == __uuidof(CVobSubFile)) {
CVobSubFile* pVSF = (CVobSubFile*)(ISubStream*)pSubStream;
if(fApplyDefStyle) {
pVSF->SetAlignment(s.fOverridePlacement, s.nHorPos, s.nVerPos, 1, 1);
}
} else if(clsid == __uuidof(CVobSubStream)) {
CVobSubStream* pVSS = (CVobSubStream*)(ISubStream*)pSubStream;
if(fApplyDefStyle) {
pVSS->SetAlignment(s.fOverridePlacement, s.nHorPos, s.nVerPos, 1, 1);
}
} else if(clsid == __uuidof(CRenderedTextSubtitle)) {
CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)pSubStream;
STSStyle style;
if(fApplyDefStyle || pRTS->m_fUsingAutoGeneratedDefaultStyle) {
style = s.subdefstyle;
if(s.fOverridePlacement) {
style.scrAlignment = 2;
int w = pRTS->m_dstScreenSize.cx;
int h = pRTS->m_dstScreenSize.cy;
int mw = w - style.marginRect.left - style.marginRect.right;
style.marginRect.bottom = h - MulDiv(h, s.nVerPos, 100);
style.marginRect.left = MulDiv(w, s.nHorPos, 100) - mw/2;
style.marginRect.right = w - (style.marginRect.left + mw);
}
bool res = pRTS->SetDefaultStyle(style);
UNUSED_ALWAYS(res);
}
if(pRTS->GetDefaultStyle(style) && style.relativeTo == 2) {
style.relativeTo = s.subdefstyle.relativeTo;
pRTS->SetDefaultStyle(style);
}
pRTS->SetOverride(s.fUseDefaultSubtitlesStyle, &s.subdefstyle);
pRTS->Deinit();
}
}
if(!fApplyDefStyle) {
m_iSubtitleSel = -1;
if(pSubStream) {
int i = 0;
POSITION pos = m_pSubStreams.GetHeadPosition();
while(pos) {
CComPtr pSubStream2 = m_pSubStreams.GetNext(pos);
if(pSubStream == pSubStream2) {
m_iSubtitleSel = i + pSubStream2->GetStream();
break;
}
i += pSubStream2->GetStreamCount();
}
}
}
m_nSubtitleId = (DWORD_PTR)pSubStream;
if(m_pCAP) {
m_pCAP->SetSubPicProvider(CComQIPtr(pSubStream));
m_wndSubresyncBar.SetSubtitle(pSubStream, m_pCAP->GetFPS());
}
}
void CMainFrame::ReplaceSubtitle(ISubStream* pSubStreamOld, ISubStream* pSubStreamNew)
{
POSITION pos = m_pSubStreams.GetHeadPosition();
while(pos) {
POSITION cur = pos;
if(pSubStreamOld == m_pSubStreams.GetNext(pos)) {
m_pSubStreams.SetAt(cur, pSubStreamNew);
UpdateSubtitle();
break;
}
}
}
void CMainFrame::InvalidateSubtitle(DWORD_PTR nSubtitleId, REFERENCE_TIME rtInvalidate)
{
if(m_pCAP) {
if(nSubtitleId == -1 || nSubtitleId == m_nSubtitleId) {
m_pCAP->Invalidate(rtInvalidate);
}
}
}
void CMainFrame::ReloadSubtitle()
{
POSITION pos = m_pSubStreams.GetHeadPosition();
while(pos) {
m_pSubStreams.GetNext(pos)->Reload();
}
UpdateSubtitle();
}
void CMainFrame::SetSubtitleTrackIdx(int index)
{
if(m_iMediaLoadState == MLS_LOADED) {
if (index < 0) {
m_iSubtitleSel ^= 0x80000000;
} else {
POSITION pos = m_pSubStreams.FindIndex(index);
if(pos) {
m_iSubtitleSel = index;
}
}
UpdateSubtitle();
AfxGetAppSettings().fEnableSubtitles = !(m_iSubtitleSel & 0x80000000);
}
}
void CMainFrame::SetAudioTrackIdx(int index)
{
if(m_iMediaLoadState == MLS_LOADED) {
CComQIPtr pSS = FindFilter(__uuidof(CAudioSwitcherFilter), pGB);
if(!pSS) {
pSS = FindFilter(L"{D3CD7858-971A-4838-ACEC-40CA5D529DC8}", pGB); // morgan's switcher
}
DWORD cStreams = 0;
DWORD dwFlags = AMSTREAMSELECTENABLE_ENABLE;
if(pSS && SUCCEEDED(pSS->Count(&cStreams)))
if((index >= 0) && (index < ((int)cStreams))) {
pSS->Enable(index, dwFlags);
}
}
}
REFERENCE_TIME CMainFrame::GetPos()
{
return(m_iMediaLoadState == MLS_LOADED ? m_wndSeekBar.GetPos() : 0);
}
REFERENCE_TIME CMainFrame::GetDur()
{
__int64 start, stop;
m_wndSeekBar.GetRange(start, stop);
return(m_iMediaLoadState == MLS_LOADED ? stop : 0);
}
void CMainFrame::SeekTo(REFERENCE_TIME rtPos, bool fSeekToKeyFrame)
{
OAFilterState fs = GetMediaState();
if(rtPos < 0) {
rtPos = 0;
}
m_nStepForwardCount = 0;
if(GetPlaybackMode() != PM_CAPTURE) {
__int64 start, stop;
m_wndSeekBar.GetRange(start, stop);
GUID tf;
pMS->GetTimeFormat(&tf);
if(start && stop) rtPos = min(rtPos, stop);
m_wndStatusBar.SetStatusTimer(rtPos, stop, !!m_wndSubresyncBar.IsWindowVisible(), &tf);
m_OSD.DisplayMessage(OSD_TOPLEFT, m_wndStatusBar.GetStatusTimer(), 1500);
}
if(GetPlaybackMode() == PM_FILE) {
if(fs == State_Stopped) {
SendMessage(WM_COMMAND, ID_PLAY_PAUSE);
}
HRESULT hr;
if(fSeekToKeyFrame) {
if(!m_kfs.IsEmpty()) {
int i = rangebsearch(rtPos, m_kfs);
if(i >= 0 && i < m_kfs.GetCount()) {
rtPos = m_kfs[i];
}
}
}
hr = pMS->SetPositions(&rtPos, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning);
} else if(GetPlaybackMode() == PM_DVD && m_iDVDDomain == DVD_DOMAIN_Title) {
if(fs != State_Running) {
SendMessage(WM_COMMAND, ID_PLAY_PLAY);
}
DVD_HMSF_TIMECODE tc = RT2HMSF(rtPos);
pDVDC->PlayAtTime(&tc, DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
// if(fs != State_Running)
// SendMessage(WM_COMMAND, ID_PLAY_PAUSE);
} else if(GetPlaybackMode() == PM_CAPTURE) {
TRACE(_T("Warning (CMainFrame::SeekTo): Trying to seek in capture mode"));
}
m_fEndOfStream = false;
SendCurrentPositionToApi(true);
}
void CMainFrame::CleanGraph()
{
if(!pGB) {
return;
}
BeginEnumFilters(pGB, pEF, pBF) {
CComQIPtr pAMMF(pBF);
if(pAMMF && (pAMMF->GetMiscFlags()&AM_FILTER_MISC_FLAGS_IS_SOURCE)) {
continue;
}
// some capture filters forget to set AM_FILTER_MISC_FLAGS_IS_SOURCE
// or to implement the IAMFilterMiscFlags interface
if(pBF == pVidCap || pBF == pAudCap) {
continue;
}
if(CComQIPtr(pBF)) {
continue;
}
int nIn, nOut, nInC, nOutC;
if(CountPins(pBF, nIn, nOut, nInC, nOutC) > 0 && (nInC+nOutC) == 0) {
TRACE(CStringW(L"Removing: ") + GetFilterName(pBF) + '\n');
pGB->RemoveFilter(pBF);
pEF->Reset();
}
}
EndEnumFilters;
}
#define AUDIOBUFFERLEN 500
static void SetLatency(IBaseFilter* pBF, int cbBuffer)
{
BeginEnumPins(pBF, pEP, pPin) {
if(CComQIPtr pAMBN = pPin) {
ALLOCATOR_PROPERTIES ap;
ap.cbAlign = -1; // -1 means no preference.
ap.cbBuffer = cbBuffer;
ap.cbPrefix = -1;
ap.cBuffers = -1;
pAMBN->SuggestAllocatorProperties(&ap);
}
}
EndEnumPins;
}
HRESULT CMainFrame::BuildCapture(IPin* pPin, IBaseFilter* pBF[3], const GUID& majortype, AM_MEDIA_TYPE* pmt)
{
IBaseFilter* pBuff = pBF[0];
IBaseFilter* pEnc = pBF[1];
IBaseFilter* pMux = pBF[2];
if(!pPin || !pMux) {
return E_FAIL;
}
CString err;
HRESULT hr = S_OK;
CFilterInfo fi;
if(FAILED(pMux->QueryFilterInfo(&fi)) || !fi.pGraph) {
pGB->AddFilter(pMux, L"Multiplexer");
}
CStringW prefix, prefixl;
if(majortype == MEDIATYPE_Video) {
prefix = L"Video ";
} else if(majortype == MEDIATYPE_Audio) {
prefix = L"Audio ";
}
prefixl = prefix;
prefixl.MakeLower();
if(pBuff) {
hr = pGB->AddFilter(pBuff, prefix + L"Buffer");
if(FAILED(hr)) {
err = _T("Can't add ") + CString(prefixl) + _T("buffer filter");
AfxMessageBox(err);
return hr;
}
hr = pGB->ConnectFilter(pPin, pBuff);
if(FAILED(hr)) {
err = _T("Error connecting the ") + CString(prefixl) + _T("buffer filter");
AfxMessageBox(err);
return(hr);
}
pPin = GetFirstPin(pBuff, PINDIR_OUTPUT);
}
if(pEnc) {
hr = pGB->AddFilter(pEnc, prefix + L"Encoder");
if(FAILED(hr)) {
err = _T("Can't add ") + CString(prefixl) + _T("encoder filter");
AfxMessageBox(err);
return hr;
}
hr = pGB->ConnectFilter(pPin, pEnc);
if(FAILED(hr)) {
err = _T("Error connecting the ") + CString(prefixl) + _T("encoder filter");
AfxMessageBox(err);
return(hr);
}
pPin = GetFirstPin(pEnc, PINDIR_OUTPUT);
if(CComQIPtr pAMSC = pPin) {
if(pmt->majortype == majortype) {
hr = pAMSC->SetFormat(pmt);
if(FAILED(hr)) {
err = _T("Can't set compression format on the ") + CString(prefixl) + _T("encoder filter");
AfxMessageBox(err);
return(hr);
}
}
}
}
// if(pMux)
{
hr = pGB->ConnectFilter(pPin, pMux);
if(FAILED(hr)) {
err = _T("Error connecting ") + CString(prefixl) + _T(" to the muliplexer filter");
AfxMessageBox(err);
return(hr);
}
}
CleanGraph();
return S_OK;
}
bool CMainFrame::BuildToCapturePreviewPin(
IBaseFilter* pVidCap, IPin** ppVidCapPin, IPin** ppVidPrevPin,
IBaseFilter* pAudCap, IPin** ppAudCapPin, IPin** ppAudPrevPin)
{
HRESULT hr;
*ppVidCapPin = *ppVidPrevPin = NULL;
*ppAudCapPin = *ppAudPrevPin = NULL;
CComPtr pDVAudPin;
if(pVidCap) {
CComPtr pPin;
if(!pAudCap // only look for interleaved stream when we don't use any other audio capture source
&& SUCCEEDED(pCGB->FindPin(pVidCap, PINDIR_OUTPUT, &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Interleaved, TRUE, 0, &pPin))) {
CComPtr pDVSplitter;
hr = pDVSplitter.CoCreateInstance(CLSID_DVSplitter);
hr = pGB->AddFilter(pDVSplitter, L"DV Splitter");
hr = pCGB->RenderStream(NULL, &MEDIATYPE_Interleaved, pPin, NULL, pDVSplitter);
pPin = NULL;
hr = pCGB->FindPin(pDVSplitter, PINDIR_OUTPUT, NULL, &MEDIATYPE_Video, TRUE, 0, &pPin);
hr = pCGB->FindPin(pDVSplitter, PINDIR_OUTPUT, NULL, &MEDIATYPE_Audio, TRUE, 0, &pDVAudPin);
CComPtr pDVDec;
hr = pDVDec.CoCreateInstance(CLSID_DVVideoCodec);
hr = pGB->AddFilter(pDVDec, L"DV Video Decoder");
hr = pGB->ConnectFilter(pPin, pDVDec);
pPin = NULL;
hr = pCGB->FindPin(pDVDec, PINDIR_OUTPUT, NULL, &MEDIATYPE_Video, TRUE, 0, &pPin);
} else if(SUCCEEDED(pCGB->FindPin(pVidCap, PINDIR_OUTPUT, &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, TRUE, 0, &pPin))) {
} else {
AfxMessageBox(_T("No video capture pin was found"));
return(false);
}
CComPtr pSmartTee;
hr = pSmartTee.CoCreateInstance(CLSID_SmartTee);
hr = pGB->AddFilter(pSmartTee, L"Smart Tee (video)");
hr = pGB->ConnectFilter(pPin, pSmartTee);
hr = pSmartTee->FindPin(L"Preview", ppVidPrevPin);
hr = pSmartTee->FindPin(L"Capture", ppVidCapPin);
}
if(pAudCap || pDVAudPin) {
CComPtr pPin;
if(pDVAudPin) {
pPin = pDVAudPin;
} else if(SUCCEEDED(pCGB->FindPin(pAudCap, PINDIR_OUTPUT, &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, TRUE, 0, &pPin))) {
} else {
AfxMessageBox(_T("No audio capture pin was found"));
return(false);
}
CComPtr pSmartTee;
hr = pSmartTee.CoCreateInstance(CLSID_SmartTee);
hr = pGB->AddFilter(pSmartTee, L"Smart Tee (audio)");
hr = pGB->ConnectFilter(pPin, pSmartTee);
hr = pSmartTee->FindPin(L"Preview", ppAudPrevPin);
hr = pSmartTee->FindPin(L"Capture", ppAudCapPin);
}
return(true);
}
bool CMainFrame::BuildGraphVideoAudio(int fVPreview, bool fVCapture, int fAPreview, bool fACapture)
{
if(!pCGB) {
return(false);
}
SaveMediaState;
HRESULT hr;
pGB->NukeDownstream(pVidCap);
pGB->NukeDownstream(pAudCap);
CleanGraph();
if(pAMVSCCap) {
hr = pAMVSCCap->SetFormat(&m_wndCaptureBar.m_capdlg.m_mtv);
}
if(pAMVSCPrev) {
hr = pAMVSCPrev->SetFormat(&m_wndCaptureBar.m_capdlg.m_mtv);
}
if(pAMASC) {
hr = pAMASC->SetFormat(&m_wndCaptureBar.m_capdlg.m_mta);
}
CComPtr pVidBuffer = m_wndCaptureBar.m_capdlg.m_pVidBuffer;
CComPtr pAudBuffer = m_wndCaptureBar.m_capdlg.m_pAudBuffer;
CComPtr pVidEnc = m_wndCaptureBar.m_capdlg.m_pVidEnc;
CComPtr pAudEnc = m_wndCaptureBar.m_capdlg.m_pAudEnc;
CComPtr pMux = m_wndCaptureBar.m_capdlg.m_pMux;
CComPtr pDst = m_wndCaptureBar.m_capdlg.m_pDst;
CComPtr pAudMux = m_wndCaptureBar.m_capdlg.m_pAudMux;
CComPtr pAudDst = m_wndCaptureBar.m_capdlg.m_pAudDst;
bool fFileOutput = (pMux && pDst) || (pAudMux && pAudDst);
bool fCapture = (fVCapture || fACapture);
if(pAudCap) {
AM_MEDIA_TYPE* pmt = &m_wndCaptureBar.m_capdlg.m_mta;
int ms = (fACapture && fFileOutput && m_wndCaptureBar.m_capdlg.m_fAudOutput) ? AUDIOBUFFERLEN : 60;
if(pMux != pAudMux && fACapture) {
SetLatency(pAudCap, -1);
} else if(pmt->pbFormat) {
SetLatency(pAudCap, ((WAVEFORMATEX*)pmt->pbFormat)->nAvgBytesPerSec * ms / 1000);
}
}
CComPtr pVidCapPin, pVidPrevPin, pAudCapPin, pAudPrevPin;
BuildToCapturePreviewPin(pVidCap, &pVidCapPin, &pVidPrevPin, pAudCap, &pAudCapPin, &pAudPrevPin);
// if(pVidCap)
{
bool fVidPrev = pVidPrevPin && fVPreview;
bool fVidCap = pVidCapPin && fVCapture && fFileOutput && m_wndCaptureBar.m_capdlg.m_fVidOutput;
if(fVPreview == 2 && !fVidCap && pVidCapPin) {
pVidPrevPin = pVidCapPin;
pVidCapPin = NULL;
}
if(fVidPrev) {
m_pCAP = NULL;
m_pCAP2 = NULL;
pGB->Render(pVidPrevPin);
pGB->FindInterface(__uuidof(ISubPicAllocatorPresenter), (void**)&m_pCAP, TRUE);
pGB->FindInterface(__uuidof(ISubPicAllocatorPresenter2), (void**)&m_pCAP2, TRUE);
}
if(fVidCap) {
IBaseFilter* pBF[3] = {pVidBuffer, pVidEnc, pMux};
HRESULT hr = BuildCapture(pVidCapPin, pBF, MEDIATYPE_Video, &m_wndCaptureBar.m_capdlg.m_mtcv);
UNUSED_ALWAYS(hr);
}
pAMDF = NULL;
pCGB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pVidCap, IID_IAMDroppedFrames, (void**)&pAMDF);
}
// if(pAudCap)
{
bool fAudPrev = pAudPrevPin && fAPreview;
bool fAudCap = pAudCapPin && fACapture && fFileOutput && m_wndCaptureBar.m_capdlg.m_fAudOutput;
if(fAPreview == 2 && !fAudCap && pAudCapPin) {
pAudPrevPin = pAudCapPin;
pAudCapPin = NULL;
}
if(fAudPrev) {
pGB->Render(pAudPrevPin);
}
if(fAudCap) {
IBaseFilter* pBF[3] = {pAudBuffer, pAudEnc, pAudMux ? pAudMux : pMux};
HRESULT hr = BuildCapture(pAudCapPin, pBF, MEDIATYPE_Audio, &m_wndCaptureBar.m_capdlg.m_mtca);
UNUSED_ALWAYS(hr);
}
}
if((pVidCap || pAudCap) && fCapture && fFileOutput) {
if(pMux != pDst) {
hr = pGB->AddFilter(pDst, L"File Writer V/A");
hr = pGB->ConnectFilter(GetFirstPin(pMux, PINDIR_OUTPUT), pDst);
}
if(CComQIPtr pCAM = pMux) {
int nIn, nOut, nInC, nOutC;
CountPins(pMux, nIn, nOut, nInC, nOutC);
pCAM->SetMasterStream(nInC-1);
// pCAM->SetMasterStream(-1);
pCAM->SetOutputCompatibilityIndex(FALSE);
}
if(CComQIPtr pCI = pMux) {
// if(FAILED(pCI->put_Mode(INTERLEAVE_CAPTURE)))
if(FAILED(pCI->put_Mode(INTERLEAVE_NONE_BUFFERED))) {
pCI->put_Mode(INTERLEAVE_NONE);
}
REFERENCE_TIME rtInterleave = 10000i64*AUDIOBUFFERLEN, rtPreroll = 0;//10000i64*500
pCI->put_Interleaving(&rtInterleave, &rtPreroll);
}
if(pMux != pAudMux && pAudMux != pAudDst) {
hr = pGB->AddFilter(pAudDst, L"File Writer A");
hr = pGB->ConnectFilter(GetFirstPin(pAudMux, PINDIR_OUTPUT), pAudDst);
}
}
REFERENCE_TIME stop = MAX_TIME;
hr = pCGB->ControlStream(&PIN_CATEGORY_CAPTURE, NULL, NULL, NULL, &stop, 0, 0); // stop in the infinite
CleanGraph();
OpenSetupVideo();
OpenSetupAudio();
OpenSetupStatsBar();
OpenSetupStatusBar();
RestoreMediaState;
return(true);
}
bool CMainFrame::StartCapture()
{
if(!pCGB || m_fCapturing) {
return(false);
}
if(!m_wndCaptureBar.m_capdlg.m_pMux && !m_wndCaptureBar.m_capdlg.m_pDst) {
return(false);
}
HRESULT hr;
::SetPriorityClass(::GetCurrentProcess(), HIGH_PRIORITY_CLASS);
// rare to see two capture filters to support IAMPushSource at the same time...
// hr = CComQIPtr(pGB)->SyncUsingStreamOffset(TRUE); // TODO:
BuildGraphVideoAudio(
m_wndCaptureBar.m_capdlg.m_fVidPreview, true,
m_wndCaptureBar.m_capdlg.m_fAudPreview, true);
hr = pME->CancelDefaultHandling(EC_REPAINT);
SendMessage(WM_COMMAND, ID_PLAY_PLAY);
m_fCapturing = true;
return(true);
}
bool CMainFrame::StopCapture()
{
if(!pCGB || !m_fCapturing) {
return(false);
}
if(!m_wndCaptureBar.m_capdlg.m_pMux && !m_wndCaptureBar.m_capdlg.m_pDst) {
return(false);
}
HRESULT hr;
m_wndStatusBar.SetStatusMessage(ResStr(IDS_CONTROLS_COMPLETING));
m_fCapturing = false;
BuildGraphVideoAudio(
m_wndCaptureBar.m_capdlg.m_fVidPreview, false,
m_wndCaptureBar.m_capdlg.m_fAudPreview, false);
hr = pME->RestoreDefaultHandling(EC_REPAINT);
::SetPriorityClass(::GetCurrentProcess(), AfxGetAppSettings().dwPriority);
m_rtDurationOverride = -1;
return(true);
}
//
void CMainFrame::ShowOptions(int idPage)
{
AppSettings& s = AfxGetAppSettings();
CPPageSheet options(ResStr(IDS_OPTIONS_CAPTION), pGB, GetModalParent(), idPage);
m_bInOptions = true;
if(options.DoModal() == IDOK) {
m_bInOptions = false;
if(!m_fFullScreen) {
SetAlwaysOnTop(s.iOnTop);
}
m_wndView.LoadLogo();
s.UpdateData(true);
}
Invalidate();
m_bInOptions = false;
}
void CMainFrame::StartWebServer(int nPort)
{
if(!m_pWebServer) {
m_pWebServer.Attach(DNew CWebServer(this, nPort));
}
}
void CMainFrame::StopWebServer()
{
if(m_pWebServer) {
m_pWebServer.Free();
}
}
CString CMainFrame::GetStatusMessage()
{
CString str;
m_wndStatusBar.m_status.GetWindowText(str);
return str;
}
void CMainFrame::SendStatusMessage(CString msg, int nTimeOut)
{
KillTimer(TIMER_STATUSERASER);
m_playingmsg.Empty();
if(nTimeOut <= 0) {
return;
}
m_playingmsg = msg;
SetTimer(TIMER_STATUSERASER, nTimeOut, NULL);
m_Lcd.SetStatusMessage(msg, nTimeOut);
}
void CMainFrame::OpenCurPlaylistItem(REFERENCE_TIME rtStart)
{
if(m_wndPlaylistBar.GetCount() == 0) {
return;
}
CPlaylistItem pli;
if(!m_wndPlaylistBar.GetCur(pli)) {
m_wndPlaylistBar.SetFirstSelected();
}
if(!m_wndPlaylistBar.GetCur(pli)) {
return;
}
CAutoPtr p(m_wndPlaylistBar.GetCurOMD(rtStart));
if(p) {
OpenMedia(p);
}
}
void CMainFrame::AddCurDevToPlaylist()
{
if(GetPlaybackMode() == PM_CAPTURE) {
m_wndPlaylistBar.Append(
m_VidDispName,
m_AudDispName,
m_wndCaptureBar.m_capdlg.GetVideoInput(),
m_wndCaptureBar.m_capdlg.GetVideoChannel(),
m_wndCaptureBar.m_capdlg.GetAudioInput()
);
}
}
void CMainFrame::OpenMedia(CAutoPtr pOMD)
{
// shortcut
if(OpenDeviceData* p = dynamic_cast(pOMD.m_p)) {
if(m_iMediaLoadState == MLS_LOADED && pAMTuner
&& m_VidDispName == p->DisplayName[0] && m_AudDispName == p->DisplayName[1]) {
m_wndCaptureBar.m_capdlg.SetVideoInput(p->vinput);
m_wndCaptureBar.m_capdlg.SetVideoChannel(p->vchannel);
m_wndCaptureBar.m_capdlg.SetAudioInput(p->ainput);
SendNowPlayingToMSN();
SendNowPlayingTomIRC();
return;
}
}
if(m_iMediaLoadState != MLS_CLOSED) {
CloseMedia();
}
// m_iMediaLoadState = MLS_LOADING; // HACK: hides the logo
AppSettings& s = AfxGetAppSettings();
bool fUseThread = m_pGraphThread && AfxGetAppSettings().fEnableWorkerThreadForOpening
// don't use a worker thread in D3DFullscreen mode except madVR
&& (!AfxGetAppSettings().IsD3DFullscreen() || AfxGetAppSettings().iDSVideoRendererType==VIDRNDT_DS_MADVR);
if(OpenFileData* p = dynamic_cast(pOMD.m_p)) {
if(p->fns.GetCount() > 0) {
engine_t e = s.m_Formats.GetEngine(p->fns.GetHead());
if (e != DirectShow /*&& e != RealMedia && e != QuickTime*/) {
fUseThread = false;
}
}
} else if(OpenDeviceData* p = dynamic_cast(pOMD.m_p)) {
fUseThread = false;
}
if(fUseThread) {
m_pGraphThread->PostThreadMessage(CGraphThread::TM_OPEN, 0, (LPARAM)pOMD.Detach());
m_bOpenedThruThread = true;
} else {
OpenMediaPrivate(pOMD);
m_bOpenedThruThread = false;
}
}
bool CMainFrame::ResetDevice()
{
if (m_pCAP) {
return m_pCAP->ResetDevice();
}
return true;
}
bool CMainFrame::DisplayChange()
{
if (m_pCAP) {
return m_pCAP->DisplayChange();
}
return true;
}
void CMainFrame::CloseMedia()
{
if(m_iMediaLoadState == MLS_CLOSING) {
TRACE(_T("WARNING: CMainFrame::CloseMedia() called twice or more\n"));
return;
}
int nTimeWaited = 0;
while(m_iMediaLoadState == MLS_LOADING) {
m_fOpeningAborted = true;
if(pGB) {
pGB->Abort(); // TODO: lock on graph objects somehow, this is not thread safe
}
if(nTimeWaited > 5*1000 && m_pGraphThread) {
MessageBeep(MB_ICONEXCLAMATION);
TRACE(_T("CRITICAL ERROR: !!! Must kill opener thread !!!"));
TerminateThread(m_pGraphThread->m_hThread, (DWORD)-1);
m_pGraphThread = (CGraphThread*)AfxBeginThread(RUNTIME_CLASS(CGraphThread));
m_bOpenedThruThread = false;
break;
}
Sleep(50);
nTimeWaited += 50;
}
m_fOpeningAborted = false;
m_closingmsg.Empty();
SetLoadState (MLS_CLOSING);
OnFilePostClosemedia();
if(m_pGraphThread && m_bOpenedThruThread) {
CAMEvent e;
m_pGraphThread->PostThreadMessage(CGraphThread::TM_CLOSE, 0, (LPARAM)&e);
e.Wait(); // either opening or closing has to be blocked to prevent reentering them, closing is the better choice
} else {
CloseMediaPrivate();
}
UnloadExternalObjects();
if (m_pFullscreenWnd->IsWindow()) {
m_pFullscreenWnd->ShowWindow (SW_HIDE);
}
}
void CMainFrame::StartTunerScan(CAutoPtr pTSD)
{
if(m_pGraphThread) {
m_pGraphThread->PostThreadMessage(CGraphThread::TM_TUNER_SCAN, 0, (LPARAM)pTSD.Detach());
} else {
DoTunerScan(pTSD);
}
}
void CMainFrame::StopTunerScan()
{
m_bStopTunerScan = true;
}
void CMainFrame::DisplayCurrentChannelOSD()
{
AppSettings& s = AfxGetAppSettings();
CDVBChannel* pChannel = s.FindChannelByPref(s.nDVBLastChannel);
CString osd;
int i = osd.Find(_T("\n"));
PresentFollowing NowNext;
if (pChannel != NULL) {
// Get EIT information:
CComQIPtr pTun = pGB;
if (pTun) {
pTun->UpdatePSI(NowNext);
}
NowNext.cPresent.Insert(0,_T(" "));
osd = pChannel->GetName()+ NowNext.cPresent;
if(i > 0) {
osd.Delete(i, osd.GetLength()-i);
}
m_OSD.DisplayMessage(OSD_TOPLEFT, osd ,3500);
}
}
void CMainFrame::DisplayCurrentChannelInfo()
{
AppSettings& s = AfxGetAppSettings();
CDVBChannel* pChannel = s.FindChannelByPref(s.nDVBLastChannel);
CString osd;
PresentFollowing NowNext;
if (pChannel != NULL) {
// Get EIT information:
CComQIPtr pTun = pGB;
if (pTun) {
pTun->UpdatePSI(NowNext);
}
osd = NowNext.cPresent + _T(". ") + NowNext.StartTime + _T(" - ") + NowNext.Duration + _T(". ") + NowNext.SummaryDesc +_T(" ");
int i = osd.Find(_T("\n"));
if(i > 0) {
osd.Delete(i, osd.GetLength()-i);
}
m_OSD.DisplayMessage(OSD_TOPLEFT, osd ,8000, 12);
}
}
//
// CGraphThread
//
IMPLEMENT_DYNCREATE(CGraphThread, CWinThread)
BOOL CGraphThread::InitInstance()
{
SetThreadName((DWORD)-1, "GraphThread");
AfxSocketInit();
return SUCCEEDED(CoInitialize(0)) ? TRUE : FALSE;
}
int CGraphThread::ExitInstance()
{
CoUninitialize();
return __super::ExitInstance();
}
BEGIN_MESSAGE_MAP(CGraphThread, CWinThread)
ON_THREAD_MESSAGE(TM_EXIT, OnExit)
ON_THREAD_MESSAGE(TM_OPEN, OnOpen)
ON_THREAD_MESSAGE(TM_CLOSE, OnClose)
ON_THREAD_MESSAGE(TM_RESET, OnReset)
ON_THREAD_MESSAGE(TM_TUNER_SCAN, OnTunerScan)
ON_THREAD_MESSAGE(TM_DISPLAY_CHANGE, OnDisplayChange)
END_MESSAGE_MAP()
void CGraphThread::OnExit(WPARAM wParam, LPARAM lParam)
{
PostQuitMessage(0);
if(CAMEvent* e = (CAMEvent*)lParam) {
e->Set();
}
}
void CGraphThread::OnOpen(WPARAM wParam, LPARAM lParam)
{
TRACE("--> CGraphThread::OnOpen on thread: %d\n", GetCurrentThreadId());
if(m_pMainFrame) {
CAutoPtr pOMD((OpenMediaData*)lParam);
m_pMainFrame->OpenMediaPrivate(pOMD);
}
}
void CGraphThread::OnClose(WPARAM wParam, LPARAM lParam)
{
if(m_pMainFrame) {
m_pMainFrame->CloseMediaPrivate();
}
if(CAMEvent* e = (CAMEvent*)lParam) {
e->Set();
}
}
void CGraphThread::OnReset(WPARAM wParam, LPARAM lParam)
{
if(m_pMainFrame) {
BOOL* b = (BOOL*)wParam;
BOOL bResult = m_pMainFrame->ResetDevice();
if (b) {
*b = bResult;
}
}
if(CAMEvent* e = (CAMEvent*)lParam) {
e->Set();
}
}
void CGraphThread::OnTunerScan(WPARAM wParam, LPARAM lParam)
{
if(m_pMainFrame) {
CAutoPtr pTSD((TunerScanData*)lParam);
m_pMainFrame->DoTunerScan(pTSD);
}
}
void CGraphThread::OnDisplayChange(WPARAM wParam, LPARAM lParam)
{
if(m_pMainFrame) {
m_pMainFrame->DisplayChange();
}
}
// ==== Added by CASIMIR666
void CMainFrame::SetLoadState(MPC_LOADSTATE iState)
{
m_iMediaLoadState = iState;
SendAPICommand (CMD_STATE, L"%d", m_iMediaLoadState);
}
void CMainFrame::SetPlayState(MPC_PLAYSTATE iState)
{
m_Lcd.SetPlayState((CMPC_Lcd::PlayState)iState);
SendAPICommand (CMD_PLAYMODE, L"%d", iState);
if (m_fEndOfStream) {
SendAPICommand (CMD_NOTIFYENDOFSTREAM, L"\0"); // do not pass NULL here!
}
// Prevent sleep when playing audio and/or video, but allow screensaver when only audio
if(!m_fAudioOnly) {
SetThreadExecutionState (iState == PS_PLAY ? ES_CONTINUOUS | ES_DISPLAY_REQUIRED | ES_SYSTEM_REQUIRED : ES_CONTINUOUS);
} else {
SetThreadExecutionState (iState == PS_PLAY ? ES_CONTINUOUS | ES_SYSTEM_REQUIRED : ES_CONTINUOUS);
}
// Set thumbnails button state
UpdateThumbarButton();
}
bool CMainFrame::CreateFullScreenWindow()
{
HMONITOR hMonitor;
MONITORINFOEX MonitorInfo;
CRect MonitorRect;
if (m_pFullscreenWnd->IsWindow()) {
m_pFullscreenWnd->DestroyWindow();
}
ZeroMemory (&MonitorInfo, sizeof(MonitorInfo));
MonitorInfo.cbSize = sizeof(MonitorInfo);
CMonitors monitors;
CString str;
CMonitor monitor;
AppSettings& s = AfxGetAppSettings();
hMonitor = NULL;
if(!s.iMonitor) {
if(s.strFullScreenMonitor == _T("Current")) {
hMonitor = MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST);
} else {
for ( int i = 0; i < monitors.GetCount(); i++ ) {
monitor = monitors.GetMonitor( i );
monitor.GetName(str);
if((monitor.IsMonitor()) && (s.strFullScreenMonitor == str)) {
hMonitor = monitor;
break;
}
}
if(!hMonitor) {
hMonitor = MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST);
}
}
} else {
hMonitor = MonitorFromWindow (m_hWnd, 0);
}
if (GetMonitorInfo (hMonitor, &MonitorInfo)) {
MonitorRect = CRect (MonitorInfo.rcMonitor);
// Window creation
DWORD dwStyle = WS_POPUP | WS_VISIBLE ;
m_fullWndSize.cx = MonitorRect.Width();
m_fullWndSize.cy = MonitorRect.Height();
m_pFullscreenWnd->CreateEx (WS_EX_TOPMOST | WS_EX_TOOLWINDOW, _T(""), ResStr(IDS_MAINFRM_136), dwStyle, MonitorRect.left, MonitorRect.top, MonitorRect.Width(), MonitorRect.Height(), NULL, NULL, NULL);
// SetWindowLong(m_pFullscreenWnd->m_hWnd, GWL_EXSTYLE, WS_EX_TOPMOST); // TODO : still freezing sometimes...
/*
CRect r;
GetWindowRect(r);
int x = MonitorRect.left + (MonitorRect.Width()/2)-(r.Width()/2);
int y = MonitorRect.top + (MonitorRect.Height()/2)-(r.Height()/2);
int w = r.Width();
int h = r.Height();
MoveWindow(x, y, w, h);
*/
}
return m_pFullscreenWnd->IsWindow();
}
bool CMainFrame::IsD3DFullScreenMode() const
{
return m_pFullscreenWnd->IsWindow();
};
void CMainFrame::SetVMR9ColorControl(float dBrightness, float dContrast, float dHue, float dSaturation)
{
VMR9ProcAmpControl ClrControl;
if(m_pMC && !AfxGetAppSettings().m_RenderersSettings.fVMR9MixerYUV) {
ClrControl.dwSize = sizeof(ClrControl);
ClrControl.dwFlags = ProcAmpControl9_Mask;
ClrControl.Brightness = dBrightness;
ClrControl.Contrast = dContrast;
ClrControl.Hue = dHue;
ClrControl.Saturation = dSaturation;
m_pMC->SetProcAmpControl (0, &ClrControl);
}
}
LPCTSTR CMainFrame::GetDVDAudioFormatName (DVD_AudioAttributes& ATR) const
{
switch(ATR.AudioFormat) {
case DVD_AudioFormat_AC3:
return _T("AC3");
case DVD_AudioFormat_MPEG1:
case DVD_AudioFormat_MPEG1_DRC:
return _T("MPEG1");
case DVD_AudioFormat_MPEG2:
case DVD_AudioFormat_MPEG2_DRC:
return _T("MPEG2");
case DVD_AudioFormat_LPCM:
return _T("LPCM");
case DVD_AudioFormat_DTS:
return _T("DTS");
case DVD_AudioFormat_SDDS:
return _T("SDDS");
case DVD_AudioFormat_Other:
default:
return ResStr(IDS_MAINFRM_137);
}
}
afx_msg void CMainFrame::OnGotoSubtitle(UINT nID)
{
OnPlayPause();
m_rtCurSubPos = m_wndSeekBar.GetPosReal();
m_lSubtitleShift = 0;
m_nCurSubtitle = m_wndSubresyncBar.FindNearestSub (m_rtCurSubPos, (nID == ID_GOTO_NEXT_SUB));
if ((m_nCurSubtitle != -1) && pMS) {
pMS->SetPositions (&m_rtCurSubPos, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning);
}
}
afx_msg void CMainFrame::OnShiftSubtitle(UINT nID)
{
if (m_nCurSubtitle >= 0) {
long lShift = (nID == ID_SHIFT_SUB_DOWN) ? -100 : 100;
CString strSubShift;
if (m_wndSubresyncBar.ShiftSubtitle (m_nCurSubtitle, lShift, m_rtCurSubPos)) {
m_lSubtitleShift += lShift;
if (pMS) {
pMS->SetPositions (&m_rtCurSubPos, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning);
}
}
strSubShift.Format (ResStr(IDS_MAINFRM_138), m_lSubtitleShift);
m_OSD.DisplayMessage (OSD_TOPLEFT, strSubShift);
}
}
afx_msg void CMainFrame::OnSubtitleDelay(UINT nID)
{
if(m_pCAP) {
if (m_pSubStreams.IsEmpty()) {
SendStatusMessage(ResStr(IDS_SUBTITLES_ERROR), 3000);
return;
}
int newDelay;
int oldDelay = m_pCAP->GetSubtitleDelay();
if(nID == ID_SUB_DELAY_DOWN) {
newDelay = oldDelay-AfxGetAppSettings().nSubDelayInterval;
} else {
newDelay = oldDelay+AfxGetAppSettings().nSubDelayInterval;
}
SetSubtitleDelay(newDelay);
}
}
afx_msg void CMainFrame::OnLanguage(UINT nID)
{
CMenu DefaultMenu;
CMenu* OldMenu;
AfxGetMyApp()->SetLanguage (nID - ID_LANGUAGE_ENGLISH);
m_opencds.DestroyMenu();
m_filters.DestroyMenu();
m_subtitles.DestroyMenu();
m_audios.DestroyMenu();
m_navaudio.DestroyMenu();
m_navsubtitle.DestroyMenu();
m_navangle.DestroyMenu();
m_navchapters.DestroyMenu();
m_favorites.DestroyMenu();
m_shaders.DestroyMenu();
m_recentfiles.DestroyMenu();
m_popup.DestroyMenu();
m_popup.LoadMenu(IDR_POPUP);
m_popupmain.DestroyMenu();
m_popupmain.LoadMenu(IDR_POPUPMAIN);
OldMenu = GetMenu();
DefaultMenu.LoadMenu(IDR_MAINFRAME);
SetMenu(&DefaultMenu);
m_hMenuDefault = DefaultMenu;
DefaultMenu.Detach();
// TODO : destroy old menu ???
// OldMenu->DestroyMenu();
}
afx_msg void CMainFrame::OnUpdateLanguage(CCmdUI* pCmdUI)
{
AppSettings &s = AfxGetAppSettings();
int nLang = pCmdUI->m_nID - ID_LANGUAGE_ENGLISH;
LPCTSTR strSatellite = AfxGetMyApp()->GetSatelliteDll(nLang);
if (strSatellite) {
HMODULE lib = NULL;
if ((lib = LoadLibrary(strSatellite)) != NULL) {
FreeLibrary(lib);
}
pCmdUI->Enable(lib != NULL);
}
pCmdUI->SetCheck(nLang == s.iLanguage);
}
void CMainFrame::ProcessAPICommand(COPYDATASTRUCT* pCDS)
{
CAtlList fns;
REFERENCE_TIME rtPos = 0;
long lPos = 0;
switch (pCDS->dwData) {
case CMD_OPENFILE :
fns.AddHead ((LPCWSTR)pCDS->lpData);
m_wndPlaylistBar.Open(fns, false);
OpenCurPlaylistItem();
break;
case CMD_STOP :
OnPlayStop();
break;
case CMD_CLOSEFILE :
CloseMedia();
break;
case CMD_PLAYPAUSE :
OnPlayPlaypause();
break;
case CMD_ADDTOPLAYLIST :
fns.AddHead ((LPCWSTR)pCDS->lpData);
m_wndPlaylistBar.Append(fns, true);
break;
case CMD_STARTPLAYLIST :
OpenCurPlaylistItem();
break;
case CMD_CLEARPLAYLIST :
m_wndPlaylistBar.Empty();
break;
case CMD_SETPOSITION :
DVD_HMSF_TIMECODE tcPos;
lPos = _wtol ((LPCWSTR)pCDS->lpData);
tcPos.bHours = lPos/3600;
tcPos.bMinutes = (lPos/60) % 60;
tcPos.bSeconds = lPos%60;
rtPos = HMSF2RT(tcPos);
// imianz: quick and dirty trick
// Pause->SeekTo->Play (in place of SeekTo only) seems to prevents in most cases
// some strange video effects on avi files (ex. locks a while and than running fast).
if(!m_fAudioOnly) {
SendMessage(WM_COMMAND, ID_PLAY_PAUSE);
}
SeekTo(rtPos);
if(!m_fAudioOnly) {
SendMessage(WM_COMMAND, ID_PLAY_PLAY);
// show current position overridden by play command
m_OSD.DisplayMessage(OSD_TOPLEFT, m_wndStatusBar.GetStatusTimer(), 2000);
}
break;
case CMD_SETAUDIODELAY :
rtPos = _wtol ((LPCWSTR)pCDS->lpData) * 10000;
SetAudioDelay (rtPos);
break;
case CMD_SETSUBTITLEDELAY :
SetSubtitleDelay(_wtoi((LPCWSTR)pCDS->lpData));
break;
case CMD_SETINDEXPLAYLIST :
//m_wndPlaylistBar.SetSelIdx(_wtoi((LPCWSTR)pCDS->lpData));
break;
case CMD_SETAUDIOTRACK :
SetAudioTrackIdx(_wtoi((LPCWSTR)pCDS->lpData));
break;
case CMD_SETSUBTITLETRACK :
SetSubtitleTrackIdx(_wtoi((LPCWSTR)pCDS->lpData));
break;
case CMD_GETSUBTITLETRACKS :
SendSubtitleTracksToApi();
break;
case CMD_GETAUDIOTRACKS :
SendAudioTracksToApi();
break;
case CMD_GETCURRENTPOSITION :
SendCurrentPositionToApi();
break;
case CMD_JUMPOFNSECONDS :
JumpOfNSeconds(_wtoi((LPCWSTR)pCDS->lpData));
break;
case CMD_GETPLAYLIST :
SendPlaylistToApi();
break;
case CMD_JUMPFORWARDMED :
OnPlaySeek(ID_PLAY_SEEKFORWARDMED);
break;
case CMD_JUMPBACKWARDMED :
OnPlaySeek(ID_PLAY_SEEKBACKWARDMED);
break;
case CMD_TOGGLEFULLSCREEN :
OnViewFullscreen();
break;
case CMD_INCREASEVOLUME :
m_wndToolBar.m_volctrl.IncreaseVolume();
break;
case CMD_DECREASEVOLUME :
m_wndToolBar.m_volctrl.DecreaseVolume();
break;
case CMD_SHADER_TOGGLE :
OnShaderToggle();
break;
case CMD_CLOSEAPP :
PostMessage(WM_CLOSE);
break;
case CMD_OSDSHOWMESSAGE:
ShowOSDCustomMessageApi((MPC_OSDDATA *)pCDS->lpData);
break;
}
}
void CMainFrame::SendAPICommand (MPCAPI_COMMAND nCommand, LPCWSTR fmt, ...)
{
AppSettings& s = AfxGetAppSettings();
if (s.hMasterWnd) {
COPYDATASTRUCT CDS;
TCHAR buff[800];
va_list args;
va_start(args, fmt);
_vstprintf(buff, fmt, args);
CDS.cbData = (_tcslen (buff) + 1) * sizeof(TCHAR);
CDS.dwData = nCommand;
CDS.lpData = (LPVOID)buff;
::SendMessage(s.hMasterWnd, WM_COPYDATA, (WPARAM)GetSafeHwnd(), (LPARAM)&CDS);
va_end(args);
}
}
void CMainFrame::SendNowPlayingToApi()
{
if(!AfxGetAppSettings().hMasterWnd) {
return;
}
if(m_iMediaLoadState == MLS_LOADED) {
CPlaylistItem pli;
CString title, author, description;
CString label;
long lDuration = 0;
REFERENCE_TIME rtDur;
m_wndInfoBar.GetLine(ResStr(IDS_INFOBAR_TITLE), title);
m_wndInfoBar.GetLine(ResStr(IDS_INFOBAR_AUTHOR), author);
m_wndInfoBar.GetLine(ResStr(IDS_INFOBAR_DESCRIPTION), description);
m_wndPlaylistBar.GetCur(pli);
if(!pli.m_fns.IsEmpty()) {
label = !pli.m_label.IsEmpty() ? pli.m_label : pli.m_fns.GetHead();
if(GetPlaybackMode() == PM_FILE) {
pMS->GetDuration(&rtDur);
DVD_HMSF_TIMECODE tcDur = RT2HMSF(rtDur);
lDuration = tcDur.bHours*60*60 + tcDur.bMinutes*60 + tcDur.bSeconds;
}
/*CString label = !pli.m_label.IsEmpty() ? pli.m_label : pli.m_fns.GetHead();
if(GetPlaybackMode() == PM_FILE)
{
CString fn = label;
if(fn.Find(_T("://")) >= 0) {int i = fn.Find('?'); if(i >= 0) fn = fn.Left(i);}
CPath path(fn);
path.StripPath();
path.MakePretty();
path.RemoveExtension();
title = (LPCTSTR)path;
author.Empty();
}
else if(GetPlaybackMode() == PM_CAPTURE)
{
title = label != pli.m_fns.GetHead() ? label : _T("Live");
author.Empty();
}
else if(GetPlaybackMode() == PM_DVD)
{
title = _T("DVD");
author.Empty();
}*/
}
title.Replace(L"|", L"\\|");
author.Replace(L"|", L"\\|");
description.Replace(L"|", L"\\|");
label.Replace(L"|", L"\\|");
CStringW buff;
buff.Format (L"%s|%s|%s|%s|%d", title, author, description, label, lDuration);
SendAPICommand (CMD_NOWPLAYING, buff);
SendSubtitleTracksToApi();
SendAudioTracksToApi();
}
}
void CMainFrame::SendSubtitleTracksToApi()
{
CStringW strSubs;
POSITION pos = m_pSubStreams.GetHeadPosition();
if(m_iMediaLoadState == MLS_LOADED) {
if (pos) {
while(pos) {
CComPtr pSubStream = m_pSubStreams.GetNext(pos);
for(int i = 0, j = pSubStream->GetStreamCount(); i < j; i++) {
WCHAR* pName = NULL;
if(SUCCEEDED(pSubStream->GetStreamInfo(i, &pName, NULL))) {
CString name(pName);
if (!strSubs.IsEmpty()) {
strSubs.Append (L"|");
}
name.Replace(L"|", L"\\|");
strSubs.AppendFormat(L"%s", name);
CoTaskMemFree(pName);
}
}
}
if(AfxGetAppSettings().fEnableSubtitles) {
if(m_iSubtitleSel >= 0) {
strSubs.AppendFormat(L"|%i", m_iSubtitleSel);
} else {
strSubs.Append(L"|-1");
}
} else {
strSubs.Append (L"|-1");
}
} else {
strSubs.Append (L"-1");
}
} else {
strSubs.Append (L"-2");
}
SendAPICommand (CMD_LISTSUBTITLETRACKS, strSubs);
}
void CMainFrame::SendAudioTracksToApi()
{
CStringW strAudios;
if(m_iMediaLoadState == MLS_LOADED) {
CComQIPtr 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))) {
int currentStream = -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(dwFlags == AMSTREAMSELECTINFO_EXCLUSIVE) {
currentStream = i;
}
CString name(pszName);
if (!strAudios.IsEmpty()) {
strAudios.Append (L"|");
}
name.Replace(L"|", L"\\|");
strAudios.AppendFormat(L"%s", name);
if(pmt) {
DeleteMediaType(pmt);
}
if(pszName) {
CoTaskMemFree(pszName);
}
}
strAudios.AppendFormat(L"|%i", currentStream);
} else {
strAudios.Append(L"-1");
}
} else {
strAudios.Append(L"-2");
}
SendAPICommand (CMD_LISTAUDIOTRACKS, strAudios);
}
void CMainFrame::SendPlaylistToApi()
{
CStringW strPlaylist;
int index;
POSITION pos = m_wndPlaylistBar.m_pl.GetHeadPosition(), pos2;
while(pos) {
CPlaylistItem& pli = m_wndPlaylistBar.m_pl.GetNext(pos);
if(pli.m_type == CPlaylistItem::file) {
pos2 = pli.m_fns.GetHeadPosition();
while(pos2) {
CString fn = pli.m_fns.GetNext(pos2);
if (!strPlaylist.IsEmpty()) {
strPlaylist.Append (L"|");
}
fn.Replace(L"|", L"\\|");
strPlaylist.AppendFormat(L"%s", fn);
}
}
}
index = m_wndPlaylistBar.GetSelIdx();
if (strPlaylist.IsEmpty()) {
strPlaylist.Append(L"-1");
} else {
strPlaylist.AppendFormat(L"|%i", index);
}
SendAPICommand (CMD_PLAYLIST, strPlaylist);
}
void CMainFrame::SendCurrentPositionToApi(bool fNotifySeek)
{
if(!AfxGetAppSettings().hMasterWnd) {
return;
}
if(m_iMediaLoadState == MLS_LOADED) {
long lPosition = 0;
REFERENCE_TIME rtCur;
if(m_iPlaybackMode == PM_FILE) {
pMS->GetCurrentPosition(&rtCur);
DVD_HMSF_TIMECODE tcCur = RT2HMSF(rtCur);
lPosition = tcCur.bHours*60*60 + tcCur.bMinutes*60 + tcCur.bSeconds;
}
CStringW buff;
buff.Format (L"%d", lPosition);
SendAPICommand (fNotifySeek ? CMD_NOTIFYSEEK : CMD_CURRENTPOSITION, buff);
}
}
void CMainFrame::ShowOSDCustomMessageApi(MPC_OSDDATA *osdData)
{
m_OSD.DisplayMessage ((OSD_MESSAGEPOS)osdData->nMsgPos, osdData->strMsg, osdData->nDurationMS);
}
void CMainFrame::JumpOfNSeconds(int nSeconds)
{
if(m_iMediaLoadState == MLS_LOADED) {
long lPosition = 0;
REFERENCE_TIME rtCur;
if(m_iPlaybackMode == PM_FILE) {
pMS->GetCurrentPosition(&rtCur);
DVD_HMSF_TIMECODE tcCur = RT2HMSF(rtCur);
lPosition = tcCur.bHours*60*60 + tcCur.bMinutes*60 + tcCur.bSeconds + nSeconds;
// revert the update position to REFERENCE_TIME format
tcCur.bHours = lPosition/3600;
tcCur.bMinutes = (lPosition/60) % 60;
tcCur.bSeconds = lPosition%60;
rtCur = HMSF2RT(tcCur);
// quick and dirty trick:
// pause->seekto->play seems to prevents some strange
// video effect (ex. locks for a while and than running fast)
if(!m_fAudioOnly) {
SendMessage(WM_COMMAND, ID_PLAY_PAUSE);
}
SeekTo(rtCur);
if(!m_fAudioOnly) {
SendMessage(WM_COMMAND, ID_PLAY_PLAY);
// show current position overridden by play command
m_OSD.DisplayMessage(OSD_TOPLEFT, m_wndStatusBar.GetStatusTimer(), 2000);
}
}
}
}
// TODO : to be finished !
//void CMainFrame::AutoSelectTracks()
//{
// LCID DefAudioLanguageLcid [2] = {MAKELCID( MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT), MAKELCID( MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), SORT_DEFAULT)};
// int DefAudioLanguageIndex [2] = {-1, -1};
// LCID DefSubtitleLanguageLcid [2] = {0, MAKELCID( MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT)};
// int DefSubtitleLanguageIndex[2] = {-1, -1};
// LCID Language = MAKELCID( MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
//
// if((m_iMediaLoadState == MLS_LOADING) || (m_iMediaLoadState == MLS_LOADED))
// {
// if(GetPlaybackMode() == PM_FILE)
// {
// CComQIPtr 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)))
// {
// 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;
// }
// }
//
// POSITION pos = m_pSubStreams.GetHeadPosition();
// while(pos)
// {
// CComPtr pSubStream = m_pSubStreams.GetNext(pos);
// if(!pSubStream) continue;
//
// for(int i = 0, j = pSubStream->GetStreamCount(); i < j; i++)
// {
// WCHAR* pName = NULL;
// if(SUCCEEDED(pSubStream->GetStreamInfo(i, &pName, &Language)))
// {
// if (DefAudioLanguageLcid[0] == Language) DefSubtitleLanguageIndex[0] = i;
// if (DefSubtitleLanguageLcid[1] == Language) DefSubtitleLanguageIndex[1] = i;
// CoTaskMemFree(pName);
// }
// }
// }
// }
// else if(GetPlaybackMode() == PM_DVD)
// {
// ULONG ulStreamsAvailable, ulCurrentStream;
// BOOL bIsDisabled;
//
// if(SUCCEEDED(pDVDI->GetCurrentSubpicture(&ulStreamsAvailable, &ulCurrentStream, &bIsDisabled)))
// {
// for(ULONG i = 0; i < ulStreamsAvailable; i++)
// {
// DVD_SubpictureAttributes ATR;
// if(SUCCEEDED(pDVDI->GetSubpictureLanguage(i, &Language)))
// {
// // Auto select forced subtitle
// if ((DefAudioLanguageLcid[0] == Language) && (ATR.LanguageExtension == DVD_SP_EXT_Forced))
// DefSubtitleLanguageIndex[0] = i;
//
// if (DefSubtitleLanguageLcid[1] == Language) DefSubtitleLanguageIndex[1] = i;
// }
// }
// }
//
// if(SUCCEEDED(pDVDI->GetCurrentAudio(&ulStreamsAvailable, &ulCurrentStream)))
// {
// for(ULONG i = 0; i < ulStreamsAvailable; i++)
// {
// if(SUCCEEDED(pDVDI->GetAudioLanguage(i, &Language)))
// {
// if (DefAudioLanguageLcid[0] == Language) DefAudioLanguageIndex[0] = i;
// if (DefAudioLanguageLcid[1] == Language) DefAudioLanguageIndex[1] = i;
// }
// }
// }
//
// // Select best audio/subtitles tracks
// if (DefAudioLanguageLcid[0] != -1)
// {
// pDVDC->SelectAudioStream(DefAudioLanguageIndex[0], DVD_CMD_FLAG_Block, NULL);
// if (DefSubtitleLanguageIndex[0] != -1)
// pDVDC->SelectSubpictureStream(DefSubtitleLanguageIndex[0], DVD_CMD_FLAG_Block, NULL);
// }
// else if ((DefAudioLanguageLcid[1] != -1) && (DefSubtitleLanguageLcid[1] != -1))
// {
// pDVDC->SelectAudioStream (DefAudioLanguageIndex[1], DVD_CMD_FLAG_Block, NULL);
// pDVDC->SelectSubpictureStream (DefSubtitleLanguageIndex[1], DVD_CMD_FLAG_Block, NULL);
// }
// }
//
//
// }
//}
void CMainFrame::OnFileOpendirectory()
{
if(m_iMediaLoadState == MLS_LOADING || !IsWindow(m_wndPlaylistBar)) {
return;
}
AppSettings& s = AfxGetAppSettings();
CString filter;
CAtlArray mask;
s.m_Formats.GetFilter(filter, mask);
COpenDirHelper::strLastOpenDir = s.strLastOpenDir;
TCHAR path[_MAX_PATH];
COpenDirHelper::m_incl_subdir = TRUE;
CString strTitle = ResStr(IDS_MAINFRM_DIR_TITLE);
BROWSEINFO bi;
bi.hwndOwner = m_hWnd;
bi.pidlRoot = NULL;
bi.pszDisplayName = path;
bi.lpszTitle = strTitle;
bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_VALIDATE | BIF_STATUSTEXT;
bi.lpfn = COpenDirHelper::BrowseCallbackProcDIR;
bi.lParam = 0;
bi.iImage = 0;
static LPITEMIDLIST iil;
iil = SHBrowseForFolder(&bi);
if(iil) {
SHGetPathFromIDList(iil, path);
CString _path = path;
_path.Replace('/', '\\');
if(_path[_path.GetLength()-1] != '\\') {
_path += '\\';
}
s.strLastOpenDir = _path;
CAtlList sl;
sl.AddTail(_path);
if(COpenDirHelper::m_incl_subdir) {
COpenDirHelper::RecurseAddDir(_path, &sl);
}
if(m_wndPlaylistBar.IsWindowVisible()) {
m_wndPlaylistBar.Append(sl, true);
} else {
m_wndPlaylistBar.Open(sl, true);
OpenCurPlaylistItem();
}
}
}
#define GetAValue(rgb) (rgb >> 24)
HRESULT CMainFrame::CreateThumbnailToolbar()
{
if(!AfxGetAppSettings().fUseWin7TaskBar) {
return E_FAIL;
}
DWORD dwMajor = LOBYTE(LOWORD(GetVersion()));
DWORD dwMinor = HIBYTE(LOWORD(GetVersion()));
if (!( dwMajor > 6 || ( dwMajor == 6 && dwMinor > 0 ))) {
return E_FAIL;
}
if(m_pTaskbarList) {
m_pTaskbarList->Release();
}
HRESULT hr = CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&m_pTaskbarList));
if (SUCCEEDED(hr)) {
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
CGdiPlusBitmapResource* pBitmap = new CGdiPlusBitmapResource;
if (!pBitmap->Load(_T("W7_TOOLBAR"), _T("PNG"), AfxGetInstanceHandle())) {
delete pBitmap;
Gdiplus::GdiplusShutdown(m_gdiplusToken);
m_pTaskbarList->Release();
return E_FAIL;
}
unsigned long Color = 0xFFFFFFFF;
unsigned int A = GetAValue(Color);
unsigned int R = GetRValue(Color);
unsigned int G = GetGValue(Color);
unsigned int B = GetBValue(Color);
Gdiplus::Color co(A,R,G,B);
HBITMAP hB = 0;
pBitmap->m_pBitmap->GetHBITMAP(co,&hB);
if (!hB) {
m_pTaskbarList->Release();
delete pBitmap;
Gdiplus::GdiplusShutdown(m_gdiplusToken);
return E_FAIL;
}
// Check dimensions
BITMAP bi = {0};
GetObject((HANDLE)hB,sizeof(bi),&bi);
if (bi.bmHeight == 0) {
DeleteObject(hB);
m_pTaskbarList->Release();
delete pBitmap;
Gdiplus::GdiplusShutdown(m_gdiplusToken);
return E_FAIL;
}
int nI = bi.bmWidth/bi.bmHeight;
HIMAGELIST himl = ImageList_Create(bi.bmHeight,bi.bmHeight,ILC_COLOR32,nI,0);
// Add the bitmap
ImageList_Add(himl,hB,0);
hr = m_pTaskbarList->ThumbBarSetImageList(m_hWnd,himl);
DeleteObject(hB);
if (SUCCEEDED(hr)) {
THUMBBUTTON buttons[5] = {};
// SEEK BACKWARD
buttons[0].dwMask = THB_BITMAP | THB_TOOLTIP | THB_FLAGS;
buttons[0].dwFlags = THBF_DISABLED;//THBF_ENABLED;
buttons[0].iId = IDTB_BUTTON3;
buttons[0].iBitmap = 0;
StringCchCopy(buttons[0].szTip, countof(buttons[0].szTip), ResStr(IDS_MPLAYERC_26));
// STOP
buttons[1].dwMask = THB_BITMAP | THB_TOOLTIP | THB_FLAGS;
buttons[1].dwFlags = THBF_DISABLED;//THBF_ENABLED;
buttons[1].iId = IDTB_BUTTON1;
buttons[1].iBitmap = 1;
StringCchCopy(buttons[1].szTip, countof(buttons[1].szTip), ResStr(IDS_AG_STOP));
// PLAY/PAUSE
buttons[2].dwMask = THB_BITMAP | THB_TOOLTIP | THB_FLAGS;
buttons[2].dwFlags = THBF_DISABLED;//THBF_ENABLED;
buttons[2].iId = IDTB_BUTTON2;
buttons[2].iBitmap = 3;
StringCchCopy(buttons[2].szTip, countof(buttons[2].szTip), ResStr(IDS_AG_PLAYPAUSE));
// SEEK FORWARD
buttons[3].dwMask = THB_BITMAP | THB_TOOLTIP | THB_FLAGS;
buttons[3].dwFlags = THBF_DISABLED;//THBF_ENABLED;
buttons[3].iId = IDTB_BUTTON4;
buttons[3].iBitmap = 4;
StringCchCopy(buttons[3].szTip, countof(buttons[3].szTip), ResStr(IDS_MPLAYERC_25));
// FULLSCREEN
buttons[4].dwMask = THB_BITMAP | THB_TOOLTIP | THB_FLAGS;
buttons[4].dwFlags = THBF_DISABLED;//THBF_ENABLED;
buttons[4].iId = IDTB_BUTTON5;
buttons[4].iBitmap = 5;
StringCchCopy(buttons[4].szTip, countof(buttons[4].szTip), ResStr(IDS_AG_FULLSCREEN));
hr = m_pTaskbarList->ThumbBarAddButtons(m_hWnd, ARRAYSIZE(buttons), buttons);
}
ImageList_Destroy(himl);
delete pBitmap;
Gdiplus::GdiplusShutdown(m_gdiplusToken);
}
return hr;
}
HRESULT CMainFrame::UpdateThumbarButton()
{
if ( !m_pTaskbarList ) {
return E_FAIL;
}
if ( !AfxGetAppSettings().fUseWin7TaskBar ) {
m_pTaskbarList->SetOverlayIcon( m_hWnd, NULL, L"" );
m_pTaskbarList->SetProgressState( m_hWnd, TBPF_NOPROGRESS );
THUMBBUTTON buttons[5] = {};
buttons[0].dwMask = THB_BITMAP | THB_TOOLTIP | THB_FLAGS;
buttons[0].dwFlags = THBF_HIDDEN;
buttons[0].iId = IDTB_BUTTON3;
buttons[1].dwMask = THB_BITMAP | THB_TOOLTIP | THB_FLAGS;
buttons[1].dwFlags = THBF_HIDDEN;
buttons[1].iId = IDTB_BUTTON1;
buttons[2].dwMask = THB_BITMAP | THB_TOOLTIP | THB_FLAGS;
buttons[2].dwFlags = THBF_HIDDEN;
buttons[2].iId = IDTB_BUTTON2;
buttons[3].dwMask = THB_BITMAP | THB_TOOLTIP | THB_FLAGS;
buttons[3].dwFlags = THBF_HIDDEN;
buttons[3].iId = IDTB_BUTTON4;
buttons[4].dwMask = THB_BITMAP | THB_TOOLTIP | THB_FLAGS;
buttons[4].dwFlags = THBF_HIDDEN;
buttons[4].iId = IDTB_BUTTON5;
HRESULT hr = m_pTaskbarList->ThumbBarUpdateButtons( m_hWnd, ARRAYSIZE(buttons), buttons );
return hr;
}
THUMBBUTTON buttons[5] = {};
buttons[0].dwMask = THB_BITMAP | THB_TOOLTIP | THB_FLAGS;
buttons[0].dwFlags = THBF_ENABLED;
buttons[0].iId = IDTB_BUTTON3;
buttons[0].iBitmap = 0;
StringCchCopy( buttons[0].szTip, _countof(buttons[0].szTip), ResStr(IDS_MPLAYERC_26) );
buttons[1].dwMask = THB_BITMAP | THB_TOOLTIP | THB_FLAGS;
buttons[1].iId = IDTB_BUTTON1;
buttons[1].iBitmap = 1;
StringCchCopy( buttons[1].szTip, _countof(buttons[1].szTip), ResStr(IDS_AG_STOP) );
buttons[2].dwMask = THB_BITMAP | THB_TOOLTIP | THB_FLAGS;
buttons[2].iId = IDTB_BUTTON2;
buttons[2].iBitmap = 3;
StringCchCopy( buttons[2].szTip, _countof(buttons[2].szTip), ResStr(IDS_AG_PLAYPAUSE) );
buttons[3].dwMask = THB_BITMAP | THB_TOOLTIP | THB_FLAGS;
buttons[3].dwFlags = THBF_ENABLED;
buttons[3].iId = IDTB_BUTTON4;
buttons[3].iBitmap = 4;
StringCchCopy( buttons[3].szTip, _countof(buttons[3].szTip), ResStr(IDS_MPLAYERC_25) );
buttons[4].dwMask = THB_BITMAP | THB_TOOLTIP | THB_FLAGS;
buttons[4].dwFlags = THBF_ENABLED;
buttons[4].iId = IDTB_BUTTON5;
buttons[4].iBitmap = 5;
StringCchCopy( buttons[4].szTip, _countof(buttons[4].szTip), ResStr(IDS_AG_FULLSCREEN) );
HICON hIcon = NULL;
if ( m_iMediaLoadState == MLS_LOADED ) {
OAFilterState fs = GetMediaState();
if ( fs == State_Running ) {
buttons[1].dwFlags = THBF_ENABLED;
buttons[2].dwFlags = THBF_ENABLED;
buttons[2].iBitmap = 2;
hIcon = AfxGetApp()->LoadIcon( IDR_TB_PLAY );
m_pTaskbarList->SetProgressState( m_hWnd, TBPF_NORMAL );
} else if ( fs == State_Stopped ) {
buttons[0].dwFlags = THBF_DISABLED;
buttons[1].dwFlags = THBF_DISABLED;
buttons[2].dwFlags = THBF_ENABLED;
buttons[2].iBitmap = 3;
buttons[3].dwFlags = THBF_DISABLED;
hIcon = AfxGetApp()->LoadIcon( IDR_TB_STOP );
m_pTaskbarList->SetProgressState( m_hWnd, TBPF_NOPROGRESS );
} else if ( fs == State_Paused ) {
buttons[1].dwFlags = THBF_ENABLED;
buttons[2].dwFlags = THBF_ENABLED;
buttons[2].iBitmap = 3;
hIcon = AfxGetApp()->LoadIcon( IDR_TB_PAUSE );
m_pTaskbarList->SetProgressState( m_hWnd, TBPF_PAUSED );
}
if ( m_fAudioOnly ) {
buttons[4].dwFlags = THBF_DISABLED;
}
m_pTaskbarList->SetOverlayIcon( m_hWnd, hIcon, L"" );
if ( hIcon != NULL ) {
DestroyIcon( hIcon );
}
} else {
buttons[0].dwFlags = THBF_DISABLED;
buttons[1].dwFlags = THBF_DISABLED;
buttons[2].dwFlags = THBF_DISABLED;
buttons[3].dwFlags = THBF_DISABLED;
buttons[4].dwFlags = THBF_DISABLED;
m_pTaskbarList->SetOverlayIcon( m_hWnd, NULL, L"" );
m_pTaskbarList->SetProgressState( m_hWnd, TBPF_NOPROGRESS );
}
HRESULT hr = m_pTaskbarList->ThumbBarUpdateButtons( m_hWnd, ARRAYSIZE(buttons), buttons );
UpdateThumbnailClip();
return hr;
}
HRESULT CMainFrame::UpdateThumbnailClip()
{
if ( !m_pTaskbarList ) {
return E_FAIL;
}
if ( (!AfxGetAppSettings().fUseWin7TaskBar) || (m_iMediaLoadState != MLS_LOADED) || (m_fAudioOnly) || m_fFullScreen ) {
return m_pTaskbarList->SetThumbnailClip( m_hWnd, NULL );
}
RECT vid_rect, result_rect;
m_wndView.GetClientRect( &vid_rect );
// NOTE: For remove menu from thumbnail clip preview
result_rect.left = 2;
result_rect.right = result_rect.left + (vid_rect.right - vid_rect.left) - 4;
result_rect.top = 22;
result_rect.bottom = result_rect.top + (vid_rect.bottom - vid_rect.top) - 4;
return m_pTaskbarList->SetThumbnailClip( m_hWnd, &result_rect );
}
LRESULT CMainFrame::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
if((message == WM_COMMAND) && (THBN_CLICKED == HIWORD(wParam))) {
int const wmId = LOWORD(wParam);
switch(wmId) {
case IDTB_BUTTON1:
SendMessage(WM_COMMAND, ID_PLAY_STOP);
break;
case IDTB_BUTTON2:
SendMessage(WM_COMMAND, ID_PLAY_PLAYPAUSE);
break;
case IDTB_BUTTON3:
SendMessage(WM_COMMAND, ID_PLAY_SEEKBACKWARDMED);
break;
case IDTB_BUTTON4:
SendMessage(WM_COMMAND, ID_PLAY_SEEKFORWARDMED);
break;
case IDTB_BUTTON5:
WINDOWPLACEMENT wp;
GetWindowPlacement(&wp);
if(wp.showCmd == SW_SHOWMINIMIZED) {
SendMessage(WM_SYSCOMMAND, SC_RESTORE, -1);
}
SetForegroundWindow();
SendMessage(WM_COMMAND, ID_VIEW_FULLSCREEN);
break;
default:
break;
}
return 0;
}
return __super::WindowProc(message, wParam, lParam);
}
UINT CMainFrame::OnPowerBroadcast(UINT nPowerEvent, UINT nEventData)
{
static BOOL bWasPausedBeforeSuspention;
OAFilterState mediaState;
switch ( nPowerEvent ) {
case PBT_APMSUSPEND: // System is suspending operation.
TRACE("OnPowerBroadcast - suspending\n"); // For user tracking
bWasPausedBeforeSuspention = FALSE; // Reset value
mediaState = GetMediaState();
if ( mediaState == State_Running ) {
bWasPausedBeforeSuspention = TRUE;
SendMessage( WM_COMMAND, ID_PLAY_PAUSE ); // Pause
}
break;
case PBT_APMRESUMEAUTOMATIC: // Operation is resuming automatically from a low-power state. This message is sent every time the system resumes.
TRACE("OnPowerBroadcast - resuming\n"); // For user tracking
// Resume if we paused before suspension.
if ( bWasPausedBeforeSuspention ) {
SendMessage( WM_COMMAND, ID_PLAY_PLAY ); // Resume
}
break;
}
return __super::OnPowerBroadcast(nPowerEvent, nEventData);
}