- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# MainFrm.cpp

    00001 /*
    00002  *      Copyright (C) 2003-2005 Gabest
    00003  *      http://www.gabest.org
    00004  *
    00005  *  This Program is free software; you can redistribute it and/or modify
    00006  *  it under the terms of the GNU General Public License as published by
    00007  *  the Free Software Foundation; either version 2, or (at your option)
    00008  *  any later version.
    00009  *
    00010  *  This Program is distributed in the hope that it will be useful,
    00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    00013  *  GNU General Public License for more details.
    00014  *
    00015  *  You should have received a copy of the GNU General Public License
    00016  *  along with GNU Make; see the file COPYING.  If not, write to
    00017  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
    00018  *  http://www.gnu.org/copyleft/gpl.html
    00019  *
    00020  */
    00021
    00022 // MainFrm.cpp : implementation of the CMainFrame class
    00023 //
    00024
    00025 #include "stdafx.h"
    00026 #include "mplayerc.h"
    00027
    00028 #include "MainFrm.h"
    00029
    00030 #include <math.h>
    00031
    00032 #include <afxpriv.h>
    00033
    00034 #include <atlconv.h>
    00035 #include <atlrx.h>
    00036 #include <atlsync.h>
    00037
    00038 #include "OpenDlg.h"
    00039 #include "SaveDlg.h"
    00040 #include "GoToDlg.h"
    00041 #include "PnSPresetsDlg.h"
    00042 #include "MediaTypesDlg.h"
    00043 #include "SaveTextFileDialog.h"
    00044 #include "FavoriteAddDlg.h"
    00045 #include "FavoriteOrganizeDlg.h"
    00046 #include "ShaderEditorDlg.h"
    00047 #include "ConvertDlg.h"
    00048
    00049 #include <mtype.h>
    00050 #include <Mpconfig.h>
    00051 #include <ks.h>
    00052 #include <ksmedia.h>
    00053 #include <dvdevcod.h>
    00054 #include <dsound.h>
    00055
    00056 #include <initguid.h>
    00057 #include <uuids.h>
    00058 #include "..\..\..\include\moreuuids.h"
    00059 #include "..\..\..\include\Ogg\OggDS.h"
    00060 #include <Qnetwork.h>
    00061 #include <qedit.h>
    00062
    00063 #include "..\..\DSUtil\DSUtil.h"
    00064
    00065 #include "GraphBuilder.h"
    00066
    00067 #include "textpassthrufilter.h"
    00068 #include "..\..\filters\filters.h"
    00069
    00070 #include "DX7AllocatorPresenter.h"
    00071 #include "DX9AllocatorPresenter.h"
    00072
    00073 #include "..\..\..\include\matroska\matroska.h"
    00074
    00075 #define DEFCLIENTW 292
    00076 #define DEFCLIENTH 200
    00077
    00078 static UINT s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
    00079 static UINT WM_NOTIFYICON = RegisterWindowMessage(TEXT("MYWM_NOTIFYICON"));
    00080
    00081 #include "..\..\filters\transform\vsfilter\IDirectVobSub.h"
    00082
    00083 class CSubClock : public CUnknown, public ISubClock
    00084 {
    00085         STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv)
    00086         {
    00087                 return
    00088                         QI(ISubClock)
    00089                         CUnknown::NonDelegatingQueryInterface(riid, ppv);
    00090         }
    00091
    00092         REFERENCE_TIME m_rt;
    00093
    00094 public:
    00095         CSubClock() : CUnknown(NAME("CSubClock"), NULL) {m_rt = 0;}
    00096
    00097         DECLARE_IUNKNOWN;
    00098
    00099         // ISubClock
    00100         STDMETHODIMP SetTime(REFERENCE_TIME rt) {m_rt = rt; return S_OK;}
    00101         STDMETHODIMP_(REFERENCE_TIME) GetTime() {return(m_rt);}
    00102 };
    00103
    00104 //
    00105
    00106 #define SaveMediaState \
    00107         OAFilterState __fs = GetMediaState(); \
    00108  \
    00109         REFERENCE_TIME __rt = 0; \
    00110         if(m_iMediaLoadState == MLS_LOADED) __rt = GetPos(); \
    00111  \
    00112         if(__fs != State_Stopped) \
    00113                 SendMessage(WM_COMMAND, ID_PLAY_STOP); \
    00114
    00115
    00116 #define RestoreMediaState \
    00117         if(m_iMediaLoadState == MLS_LOADED) \
    00118         { \
    00119                 SeekTo(__rt); \
    00120  \
    00121                 if(__fs == State_Stopped) \
    00122                         SendMessage(WM_COMMAND, ID_PLAY_STOP); \
    00123                 else if(__fs == State_Paused) \
    00124                         SendMessage(WM_COMMAND, ID_PLAY_PAUSE); \
    00125                 else if(__fs == State_Running) \
    00126                         SendMessage(WM_COMMAND, ID_PLAY_PLAY); \
    00127         } \
    00128
    00129 /*
    00130 #ifdef _DEBUG
    00131 #define new DEBUG_NEW
    00132 #undef THIS_FILE
    00133 static char THIS_FILE[] = __FILE__;
    00134 #endif
    00135 */
    00137 // CMainFrame
    00138
    00139 IMPLEMENT_DYNAMIC(CMainFrame, CFrameWnd)
    00140
    00141 BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
    00142         ON_WM_CREATE()
    00143         ON_WM_DESTROY()
    00144         ON_WM_CLOSE()
    00145
    00146         ON_REGISTERED_MESSAGE(s_uTaskbarRestart, OnTaskBarRestart)
    00147         ON_REGISTERED_MESSAGE(WM_NOTIFYICON, OnNotifyIcon)
    00148
    00149         ON_WM_SETFOCUS()
    00150         ON_WM_GETMINMAXINFO()
    00151         ON_WM_MOVE()
    00152         ON_WM_SIZE()
    00153         ON_MESSAGE_VOID(WM_DISPLAYCHANGE, OnDisplayChange)
    00154
    00155         ON_WM_SYSCOMMAND()
    00156         ON_WM_ACTIVATEAPP()
    00157         ON_MESSAGE(WM_APPCOMMAND, OnAppCommand)
    00158
    00159         ON_WM_TIMER()
    00160
    00161         ON_MESSAGE(WM_GRAPHNOTIFY, OnGraphNotify)
    00162         ON_MESSAGE(WM_REARRANGERENDERLESS, OnRepaintRenderLess)
    00163         ON_MESSAGE(WM_RESUMEFROMSTATE, OnResumeFromState)
    00164
    00165         ON_WM_LBUTTONDOWN()
    00166         ON_WM_LBUTTONUP()
    00167         ON_WM_LBUTTONDBLCLK()
    00168         ON_WM_MBUTTONDOWN()
    00169         ON_WM_MBUTTONUP()
    00170         ON_WM_MBUTTONDBLCLK()
    00171         ON_WM_RBUTTONDOWN()
    00172         ON_WM_RBUTTONUP()
    00173         ON_WM_RBUTTONDBLCLK()
    00174         ON_MESSAGE(WM_XBUTTONDOWN, OnXButtonDown)
    00175         ON_MESSAGE(WM_XBUTTONUP, OnXButtonUp)
    00176         ON_MESSAGE(WM_XBUTTONDBLCLK, OnXButtonDblClk)
    00177         ON_WM_MOUSEWHEEL()
    00178         ON_WM_MOUSEMOVE()
    00179
    00180         ON_WM_NCHITTEST()
    00181
    00182         ON_WM_HSCROLL()
    00183
    00184         ON_WM_INITMENU()
    00185         ON_WM_INITMENUPOPUP()
    00186
    00187         ON_COMMAND(ID_MENU_PLAYER_SHORT, OnMenuPlayerShort)
    00188         ON_COMMAND(ID_MENU_PLAYER_LONG, OnMenuPlayerLong)
    00189         ON_COMMAND(ID_MENU_FILTERS, OnMenuFilters)
    00190
    00191         ON_UPDATE_COMMAND_UI(ID_PLAYERSTATUS, OnUpdatePlayerStatus)
    00192
    00193         ON_COMMAND(ID_FILE_POST_OPENMEDIA, OnFilePostOpenmedia)
    00194         ON_UPDATE_COMMAND_UI(ID_FILE_POST_OPENMEDIA, OnUpdateFilePostOpenmedia)
    00195         ON_COMMAND(ID_FILE_POST_CLOSEMEDIA, OnFilePostClosemedia)
    00196         ON_UPDATE_COMMAND_UI(ID_FILE_POST_CLOSEMEDIA, OnUpdateFilePostClosemedia)
    00197
    00198         ON_COMMAND(ID_BOSS, OnBossKey)
    00199
    00200         ON_COMMAND_RANGE(ID_STREAM_AUDIO_NEXT, ID_STREAM_AUDIO_PREV, OnStreamAudio)
    00201         ON_COMMAND_RANGE(ID_STREAM_SUB_NEXT, ID_STREAM_SUB_PREV, OnStreamSub)
    00202         ON_COMMAND(ID_STREAM_SUB_ONOFF, OnStreamSubOnOff)
    00203         ON_COMMAND_RANGE(ID_OGM_AUDIO_NEXT, ID_OGM_AUDIO_PREV, OnOgmAudio)
    00204         ON_COMMAND_RANGE(ID_OGM_SUB_NEXT, ID_OGM_SUB_PREV, OnOgmSub)
    00205         ON_COMMAND_RANGE(ID_DVD_ANGLE_NEXT, ID_DVD_ANGLE_PREV, OnDvdAngle)
    00206         ON_COMMAND_RANGE(ID_DVD_AUDIO_NEXT, ID_DVD_AUDIO_PREV, OnDvdAudio)
    00207         ON_COMMAND_RANGE(ID_DVD_SUB_NEXT, ID_DVD_SUB_PREV, OnDvdSub)
    00208         ON_COMMAND(ID_DVD_SUB_ONOFF, OnDvdSubOnOff)
    00209
    00210         ON_COMMAND(ID_FILE_OPENMEDIA, OnFileOpenmedia)
    00211         ON_UPDATE_COMMAND_UI(ID_FILE_OPENMEDIA, OnUpdateFileOpen)
    00212         ON_WM_COPYDATA()
    00213         ON_COMMAND(ID_FILE_OPENDVD, OnFileOpendvd)
    00214         ON_UPDATE_COMMAND_UI(ID_FILE_OPENDVD, OnUpdateFileOpen)
    00215         ON_COMMAND(ID_FILE_OPENDEVICE, OnFileOpendevice)
    00216         ON_UPDATE_COMMAND_UI(ID_FILE_OPENDEVICE, OnUpdateFileOpen)
    00217         ON_COMMAND_RANGE(ID_FILE_OPEN_CD_START, ID_FILE_OPEN_CD_END, OnFileOpenCD)
    00218         ON_UPDATE_COMMAND_UI_RANGE(ID_FILE_OPEN_CD_START, ID_FILE_OPEN_CD_END, OnUpdateFileOpen)
    00219         ON_WM_DROPFILES()
    00220         ON_COMMAND(ID_FILE_SAVEAS, OnFileSaveas)
    00221         ON_UPDATE_COMMAND_UI(ID_FILE_SAVEAS, OnUpdateFileSaveas)
    00222         ON_COMMAND(ID_FILE_SAVE_IMAGE, OnFileSaveImage)
    00223         ON_COMMAND(ID_FILE_SAVE_IMAGE_AUTO, OnFileSaveImageAuto)
    00224         ON_UPDATE_COMMAND_UI(ID_FILE_SAVE_IMAGE, OnUpdateFileSaveImage)
    00225         ON_UPDATE_COMMAND_UI(ID_FILE_SAVE_IMAGE_AUTO, OnUpdateFileSaveImage)
    00226         ON_COMMAND(ID_FILE_CONVERT, OnFileConvert)
    00227         ON_UPDATE_COMMAND_UI(ID_FILE_CONVERT, OnUpdateFileConvert)
    00228         ON_COMMAND(ID_FILE_LOADSUBTITLE, OnFileLoadsubtitles)
    00229         ON_UPDATE_COMMAND_UI(ID_FILE_LOADSUBTITLE, OnUpdateFileLoadsubtitles)
    00230         ON_COMMAND(ID_FILE_SAVESUBTITLES, OnFileSavesubtitles)
    00231         ON_UPDATE_COMMAND_UI(ID_FILE_SAVESUBTITLES, OnUpdateFileSavesubtitles)
    00232         ON_COMMAND(ID_SUBTITLEDATABASE_SEARCH, OnSubtitledatabaseSearch)
    00233         ON_UPDATE_COMMAND_UI(ID_SUBTITLEDATABASE_SEARCH, OnUpdateSubtitledatabaseSearch)
    00234         ON_COMMAND(ID_SUBTITLEDATABASE_UPLOAD, OnSubtitledatabaseUpload)
    00235         ON_UPDATE_COMMAND_UI(ID_SUBTITLEDATABASE_UPLOAD, OnUpdateSubtitledatabaseUpload)
    00236         ON_COMMAND(ID_SUBTITLEDATABASE_DOWNLOAD, OnSubtitledatabaseDownload)
    00237         ON_UPDATE_COMMAND_UI(ID_SUBTITLEDATABASE_DOWNLOAD, OnUpdateSubtitledatabaseDownload)
    00238         ON_COMMAND(ID_FILE_PROPERTIES, OnFileProperties)
    00239         ON_UPDATE_COMMAND_UI(ID_FILE_PROPERTIES, OnUpdateFileProperties)
    00240         ON_COMMAND(ID_FILE_CLOSEPLAYLIST, OnFileClosePlaylist)
    00241         ON_COMMAND(ID_FILE_CLOSEMEDIA, OnFileCloseMedia)
    00242         ON_UPDATE_COMMAND_UI(ID_FILE_CLOSEMEDIA, OnUpdateFileClose)
    00243
    00244         ON_COMMAND(ID_VIEW_CAPTIONMENU, OnViewCaptionmenu)
    00245         ON_UPDATE_COMMAND_UI(ID_VIEW_CAPTIONMENU, OnUpdateViewCaptionmenu)
    00246         ON_COMMAND_RANGE(ID_VIEW_SEEKER, ID_VIEW_STATUS, OnViewControlBar)
    00247         ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_SEEKER, ID_VIEW_STATUS, OnUpdateViewControlBar)
    00248         ON_COMMAND(ID_VIEW_SUBRESYNC, OnViewSubresync)
    00249         ON_UPDATE_COMMAND_UI(ID_VIEW_SUBRESYNC, OnUpdateViewSubresync)
    00250         ON_COMMAND(ID_VIEW_PLAYLIST, OnViewPlaylist)
    00251         ON_UPDATE_COMMAND_UI(ID_VIEW_PLAYLIST, OnUpdateViewPlaylist)
    00252         ON_COMMAND(ID_VIEW_CAPTURE, OnViewCapture)
    00253         ON_UPDATE_COMMAND_UI(ID_VIEW_CAPTURE, OnUpdateViewCapture)
    00254         ON_COMMAND(ID_VIEW_PRESETS_MINIMAL, OnViewMinimal)
    00255         ON_UPDATE_COMMAND_UI(ID_VIEW_PRESETS_MINIMAL, OnUpdateViewMinimal)
    00256         ON_COMMAND(ID_VIEW_PRESETS_COMPACT, OnViewCompact)
    00257         ON_UPDATE_COMMAND_UI(ID_VIEW_PRESETS_COMPACT, OnUpdateViewCompact)
    00258         ON_COMMAND(ID_VIEW_PRESETS_NORMAL, OnViewNormal)
    00259         ON_UPDATE_COMMAND_UI(ID_VIEW_PRESETS_NORMAL, OnUpdateViewNormal)
    00260         ON_COMMAND(ID_VIEW_FULLSCREEN, OnViewFullscreen)
    00261         ON_COMMAND(ID_VIEW_FULLSCREEN_SECONDARY, OnViewFullscreenSecondary)
    00262         ON_UPDATE_COMMAND_UI(ID_VIEW_FULLSCREEN, OnUpdateViewFullscreen)
    00263         ON_COMMAND_RANGE(ID_VIEW_ZOOM_50, ID_VIEW_ZOOM_200, OnViewZoom)
    00264         ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_ZOOM_50, ID_VIEW_ZOOM_200, OnUpdateViewZoom)
    00265         ON_COMMAND_RANGE(ID_VIEW_VF_HALF, ID_VIEW_VF_FROMOUTSIDE, OnViewDefaultVideoFrame)
    00266         ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_VF_HALF, ID_VIEW_VF_FROMOUTSIDE, OnUpdateViewDefaultVideoFrame)
    00267         ON_COMMAND(ID_VIEW_VF_KEEPASPECTRATIO, OnViewKeepaspectratio)
    00268         ON_UPDATE_COMMAND_UI(ID_VIEW_VF_KEEPASPECTRATIO, OnUpdateViewKeepaspectratio)
    00269         ON_COMMAND(ID_VIEW_VF_COMPMONDESKARDIFF, OnViewCompMonDeskARDiff)
    00270         ON_UPDATE_COMMAND_UI(ID_VIEW_VF_COMPMONDESKARDIFF, OnUpdateViewCompMonDeskARDiff)
    00271         ON_COMMAND_RANGE(ID_VIEW_INCSIZE, ID_VIEW_RESET, OnViewPanNScan)
    00272         ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_INCSIZE, ID_VIEW_RESET, OnUpdateViewPanNScan)
    00273         ON_COMMAND_RANGE(ID_PANSCAN_MOVELEFT, ID_PANSCAN_CENTER, OnViewPanNScan)
    00274         ON_UPDATE_COMMAND_UI_RANGE(ID_PANSCAN_MOVELEFT, ID_PANSCAN_CENTER, OnUpdateViewPanNScan)
    00275         ON_COMMAND_RANGE(ID_PANNSCAN_PRESETS_START, ID_PANNSCAN_PRESETS_END, OnViewPanNScanPresets)
    00276         ON_UPDATE_COMMAND_UI_RANGE(ID_PANNSCAN_PRESETS_START, ID_PANNSCAN_PRESETS_END, OnUpdateViewPanNScanPresets)
    00277         ON_COMMAND_RANGE(ID_PANSCAN_ROTATEXP, ID_PANSCAN_ROTATEZM, OnViewRotate)
    00278         ON_UPDATE_COMMAND_UI_RANGE(ID_PANSCAN_ROTATEXP, ID_PANSCAN_ROTATEZM, OnUpdateViewRotate)
    00279         ON_COMMAND_RANGE(ID_ASPECTRATIO_START, ID_ASPECTRATIO_END, OnViewAspectRatio)
    00280         ON_UPDATE_COMMAND_UI_RANGE(ID_ASPECTRATIO_START, ID_ASPECTRATIO_END, OnUpdateViewAspectRatio)
    00281         ON_COMMAND_RANGE(ID_ONTOP_NEVER, ID_ONTOP_WHILEPLAYING, OnViewOntop)
    00282         ON_UPDATE_COMMAND_UI_RANGE(ID_ONTOP_NEVER, ID_ONTOP_WHILEPLAYING, OnUpdateViewOntop)
    00283         ON_COMMAND(ID_VIEW_OPTIONS, OnViewOptions)
    00284
    00285         ON_COMMAND(ID_PLAY_PLAY, OnPlayPlay)
    00286         ON_COMMAND(ID_PLAY_PAUSE, OnPlayPause)
    00287         ON_COMMAND(ID_PLAY_PLAYPAUSE, OnPlayPlaypause)
    00288         ON_COMMAND(ID_PLAY_STOP, OnPlayStop)
    00289         ON_UPDATE_COMMAND_UI(ID_PLAY_PLAY, OnUpdatePlayPauseStop)
    00290         ON_UPDATE_COMMAND_UI(ID_PLAY_PAUSE, OnUpdatePlayPauseStop)
    00291         ON_UPDATE_COMMAND_UI(ID_PLAY_PLAYPAUSE, OnUpdatePlayPauseStop)
    00292         ON_UPDATE_COMMAND_UI(ID_PLAY_STOP, OnUpdatePlayPauseStop)
    00293         ON_COMMAND_RANGE(ID_PLAY_FRAMESTEP, ID_PLAY_FRAMESTEPCANCEL, OnPlayFramestep)
    00294         ON_UPDATE_COMMAND_UI_RANGE(ID_PLAY_FRAMESTEP, ID_PLAY_FRAMESTEPCANCEL, OnUpdatePlayFramestep)
    00295         ON_COMMAND_RANGE(ID_PLAY_SEEKBACKWARDSMALL, ID_PLAY_SEEKFORWARDLARGE, OnPlaySeek)
    00296         ON_COMMAND_RANGE(ID_PLAY_SEEKKEYBACKWARD, ID_PLAY_SEEKKEYFORWARD, OnPlaySeekKey)
    00297         ON_UPDATE_COMMAND_UI_RANGE(ID_PLAY_SEEKBACKWARDSMALL, ID_PLAY_SEEKFORWARDLARGE, OnUpdatePlaySeek)
    00298         ON_UPDATE_COMMAND_UI_RANGE(ID_PLAY_SEEKKEYBACKWARD, ID_PLAY_SEEKKEYFORWARD, OnUpdatePlaySeek)
    00299         ON_COMMAND(ID_PLAY_GOTO, OnPlayGoto)
    00300         ON_UPDATE_COMMAND_UI(ID_PLAY_GOTO, OnUpdateGoto)
    00301         ON_COMMAND_RANGE(ID_PLAY_DECRATE, ID_PLAY_INCRATE, OnPlayChangeRate)
    00302         ON_UPDATE_COMMAND_UI_RANGE(ID_PLAY_DECRATE, ID_PLAY_INCRATE, OnUpdatePlayChangeRate)
    00303         ON_COMMAND(ID_PLAY_RESETRATE, OnPlayResetRate)
    00304         ON_UPDATE_COMMAND_UI(ID_PLAY_RESETRATE, OnUpdatePlayResetRate)
    00305         ON_COMMAND_RANGE(ID_PLAY_INCAUDDELAY, ID_PLAY_DECAUDDELAY, OnPlayChangeAudDelay)
    00306         ON_UPDATE_COMMAND_UI_RANGE(ID_PLAY_INCAUDDELAY, ID_PLAY_DECAUDDELAY, OnUpdatePlayChangeAudDelay)
    00307         ON_COMMAND_RANGE(ID_FILTERS_SUBITEM_START, ID_FILTERS_SUBITEM_END, OnPlayFilters)
    00308         ON_UPDATE_COMMAND_UI_RANGE(ID_FILTERS_SUBITEM_START, ID_FILTERS_SUBITEM_END, OnUpdatePlayFilters)
    00309         ON_COMMAND_RANGE(ID_SHADERS_START, ID_SHADERS_END, OnPlayShaders)
    00310         ON_UPDATE_COMMAND_UI_RANGE(ID_SHADERS_START, ID_SHADERS_END, OnUpdatePlayShaders)
    00311         ON_COMMAND_RANGE(ID_AUDIO_SUBITEM_START, ID_AUDIO_SUBITEM_END, OnPlayAudio)
    00312         ON_UPDATE_COMMAND_UI_RANGE(ID_AUDIO_SUBITEM_START, ID_AUDIO_SUBITEM_END, OnUpdatePlayAudio)
    00313         ON_COMMAND_RANGE(ID_SUBTITLES_SUBITEM_START, ID_SUBTITLES_SUBITEM_END, OnPlaySubtitles)
    00314         ON_UPDATE_COMMAND_UI_RANGE(ID_SUBTITLES_SUBITEM_START, ID_SUBTITLES_SUBITEM_END, OnUpdatePlaySubtitles)
    00315         ON_COMMAND_RANGE(ID_FILTERSTREAMS_SUBITEM_START, ID_FILTERSTREAMS_SUBITEM_END, OnPlayLanguage)
    00316         ON_UPDATE_COMMAND_UI_RANGE(ID_FILTERSTREAMS_SUBITEM_START, ID_FILTERSTREAMS_SUBITEM_END, OnUpdatePlayLanguage)
    00317         ON_COMMAND_RANGE(ID_VOLUME_UP, ID_VOLUME_MUTE, OnPlayVolume)
    00318         ON_COMMAND_RANGE(ID_AFTERPLAYBACK_CLOSE, ID_AFTERPLAYBACK_DONOTHING, OnAfterplayback)
    00319         ON_UPDATE_COMMAND_UI_RANGE(ID_AFTERPLAYBACK_CLOSE, ID_AFTERPLAYBACK_DONOTHING, OnUpdateAfterplayback)
    00320
    00321         ON_COMMAND_RANGE(ID_NAVIGATE_SKIPBACK, ID_NAVIGATE_SKIPFORWARD, OnNavigateSkip)
    00322         ON_UPDATE_COMMAND_UI_RANGE(ID_NAVIGATE_SKIPBACK, ID_NAVIGATE_SKIPFORWARD, OnUpdateNavigateSkip)
    00323         ON_COMMAND_RANGE(ID_NAVIGATE_SKIPBACKPLITEM, ID_NAVIGATE_SKIPFORWARDPLITEM, OnNavigateSkipPlaylistItem)
    00324         ON_UPDATE_COMMAND_UI_RANGE(ID_NAVIGATE_SKIPBACKPLITEM, ID_NAVIGATE_SKIPFORWARDPLITEM, OnUpdateNavigateSkipPlaylistItem)
    00325         ON_COMMAND_RANGE(ID_NAVIGATE_TITLEMENU, ID_NAVIGATE_CHAPTERMENU, OnNavigateMenu)
    00326         ON_UPDATE_COMMAND_UI_RANGE(ID_NAVIGATE_TITLEMENU, ID_NAVIGATE_CHAPTERMENU, OnUpdateNavigateMenu)
    00327         ON_COMMAND_RANGE(ID_NAVIGATE_AUDIO_SUBITEM_START, ID_NAVIGATE_AUDIO_SUBITEM_END, OnNavigateAudio)
    00328         ON_COMMAND_RANGE(ID_NAVIGATE_SUBP_SUBITEM_START, ID_NAVIGATE_SUBP_SUBITEM_END, OnNavigateSubpic)
    00329         ON_COMMAND_RANGE(ID_NAVIGATE_ANGLE_SUBITEM_START, ID_NAVIGATE_ANGLE_SUBITEM_END, OnNavigateAngle)
    00330         ON_COMMAND_RANGE(ID_NAVIGATE_CHAP_SUBITEM_START, ID_NAVIGATE_CHAP_SUBITEM_END, OnNavigateChapters)
    00331         ON_COMMAND_RANGE(ID_NAVIGATE_MENU_LEFT, ID_NAVIGATE_MENU_LEAVE, OnNavigateMenuItem)
    00332         ON_UPDATE_COMMAND_UI_RANGE(ID_NAVIGATE_MENU_LEFT, ID_NAVIGATE_MENU_LEAVE, OnUpdateNavigateMenuItem)
    00333
    00334         ON_COMMAND(ID_FAVORITES_ADD, OnFavoritesAdd)
    00335         ON_UPDATE_COMMAND_UI(ID_FAVORITES_ADD, OnUpdateFavoritesAdd)
    00336         ON_COMMAND(ID_FAVORITES_ORGANIZE, OnFavoritesOrganize)
    00337         ON_UPDATE_COMMAND_UI(ID_FAVORITES_ORGANIZE, OnUpdateFavoritesOrganize)
    00338         ON_COMMAND_RANGE(ID_FAVORITES_FILE_START, ID_FAVORITES_FILE_END, OnFavoritesFile)
    00339         ON_UPDATE_COMMAND_UI_RANGE(ID_FAVORITES_FILE_START, ID_FAVORITES_FILE_END, OnUpdateFavoritesFile)
    00340         ON_COMMAND_RANGE(ID_FAVORITES_DVD_START, ID_FAVORITES_DVD_END, OnFavoritesDVD)
    00341         ON_UPDATE_COMMAND_UI_RANGE(ID_FAVORITES_DVD_START, ID_FAVORITES_DVD_END, OnUpdateFavoritesDVD)
    00342         ON_COMMAND_RANGE(ID_FAVORITES_DEVICE_START, ID_FAVORITES_DEVICE_END, OnFavoritesDevice)
    00343         ON_UPDATE_COMMAND_UI_RANGE(ID_FAVORITES_DEVICE_START, ID_FAVORITES_DEVICE_END, OnUpdateFavoritesDevice)
    00344
    00345         ON_COMMAND(ID_HELP_HOMEPAGE, OnHelpHomepage)
    00346         ON_COMMAND(ID_HELP_DOCUMENTATION, OnHelpDocumentation)
    00347         ON_COMMAND(ID_HELP_DONATE, OnHelpDonate)
    00348
    00349         ON_WM_SIZING()
    00350         END_MESSAGE_MAP()
    00351
    00352
    00353 // CMainFrame construction/destruction
    00354
    00355 #pragma warning(disable : 4355)
    00356
    00357 CMainFrame::CMainFrame() :
    00358         m_dwRegister(0),
    00359         m_iMediaLoadState(MLS_CLOSED),
    00360         m_iPlaybackMode(PM_NONE),
    00361         m_iSpeedLevel(0),
    00362         m_rtDurationOverride(-1),
    00363         m_fFullScreen(false),
    00364         m_fHideCursor(false),
    00365         m_lastMouseMove(-1, -1),
    00366         m_pLastBar(NULL),
    00367         m_nLoops(0),
    00368         m_iSubtitleSel(-1),
    00369         m_ZoomX(1), m_ZoomY(1), m_PosX(0.5), m_PosY(0.5),
    00370         m_AngleX(0), m_AngleY(0), m_AngleZ(0),
    00371         m_fCustomGraph(false),
    00372         m_fRealMediaGraph(false), m_fShockwaveGraph(false), m_fQuicktimeGraph(false),
    00373         m_fFrameSteppingActive(false),
    00374         m_fEndOfStream(false),
    00375         m_fCapturing(false),
    00376         m_fLiveWM(false),
    00377         m_fOpeningAborted(false),
    00378         m_fBuffering(false),
    00379         m_fileDropTarget(this),
    00380         m_fTrayIcon(false)
    00381 {
    00382
    00383
    00384 }
    00385
    00386 CMainFrame::~CMainFrame()
    00387 {
    00388 //      m_owner.DestroyWindow();
    00389 }
    00390
    00391 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
    00392 {
    00393         if(__super::OnCreate(lpCreateStruct) == -1)
    00394                 return -1;
    00395
    00396         m_popup.LoadMenu(IDR_POPUP);
    00397         m_popupmain.LoadMenu(IDR_POPUPMAIN);
    00398
    00399         GetMenu()->ModifyMenu(ID_FAVORITES, MF_BYCOMMAND|MF_STRING, IDR_MAINFRAME, ResStr(IDS_FAVORITES_POPUP));
    00400
    00401         // create a view to occupy the client area of the frame
    00402         if(!m_wndView.Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,
    00403                 CRect(0, 0, 0, 0), this, AFX_IDW_PANE_FIRST, NULL))
    00404         {
    00405                 TRACE0("Failed to create view window\n");
    00406                 return -1;
    00407         }
    00408
    00409         // static bars
    00410
    00411         if(!m_wndStatusBar.Create(this)
    00412         || !m_wndStatsBar.Create(this)
    00413         || !m_wndInfoBar.Create(this)
    00414         || !m_wndToolBar.Create(this)
    00415         || !m_wndSeekBar.Create(this))
    00416         {
    00417                 TRACE0("Failed to create all control bars\n");
    00418                 return -1;      // fail to create
    00419         }
    00420
    00421         m_bars.AddTail(&m_wndSeekBar);
    00422         m_bars.AddTail(&m_wndToolBar);
    00423         m_bars.AddTail(&m_wndInfoBar);
    00424         m_bars.AddTail(&m_wndStatsBar);
    00425         m_bars.AddTail(&m_wndStatusBar);
    00426
    00427         m_wndSeekBar.Enable(false);
    00428
    00429         // dockable bars
    00430
    00431         EnableDocking(CBRS_ALIGN_ANY);
    00432
    00433         m_wndSubresyncBar.Create(this, &m_csSubLock);
    00434         m_wndSubresyncBar.SetBarStyle(m_wndSubresyncBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
    00435         m_wndSubresyncBar.EnableDocking(CBRS_ALIGN_ANY);
    00436         m_wndSubresyncBar.SetHeight(200);
    00437         LoadControlBar(&m_wndSubresyncBar, _T("ToolBars\\Subresync"), AFX_IDW_DOCKBAR_TOP);
    00438
    00439         m_wndPlaylistBar.Create(this);
    00440         m_wndPlaylistBar.SetBarStyle(m_wndPlaylistBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
    00441         m_wndPlaylistBar.EnableDocking(CBRS_ALIGN_ANY);
    00442         m_wndPlaylistBar.SetHeight(100);
    00443         LoadControlBar(&m_wndPlaylistBar, _T("ToolBars\\Playlist"), AFX_IDW_DOCKBAR_BOTTOM);
    00444         m_wndPlaylistBar.LoadPlaylist();
    00445
    00446         m_wndCaptureBar.Create(this);
    00447         m_wndCaptureBar.SetBarStyle(m_wndCaptureBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
    00448         m_wndCaptureBar.EnableDocking(CBRS_ALIGN_LEFT|CBRS_ALIGN_RIGHT);
    00449         LoadControlBar(&m_wndCaptureBar, _T("ToolBars\\Capture"), AFX_IDW_DOCKBAR_LEFT);
    00450
    00451         m_dockingbars.AddTail(&m_wndSubresyncBar);
    00452         m_dockingbars.AddTail(&m_wndPlaylistBar);
    00453         m_dockingbars.AddTail(&m_wndCaptureBar);
    00454
    00455         m_fileDropTarget.Register(this);
    00456
    00457         AppSettings& s = AfxGetAppSettings();
    00458
    00459         ShowControls(s.nCS);
    00460
    00461         SetAlwaysOnTop(s.iOnTop);
    00462
    00463         ShowTrayIcon(s.fTrayIcon);
    00464
    00465         SetFocus();
    00466
    00467         m_pGraphThread = (CGraphThread*)AfxBeginThread(RUNTIME_CLASS(CGraphThread));
    00468
    00469         if(m_pGraphThread)
    00470                 m_pGraphThread->SetMainFrame(this);
    00471
    00472         if(s.fEnableWebServer)
    00473                 StartWebServer(s.nWebServerPort);
    00474
    00475         return 0;
    00476 }
    00477
    00478 void CMainFrame::OnDestroy()
    00479 {
    00480         ShowTrayIcon(false);
    00481
    00482         m_fileDropTarget.Revoke();
    00483
    00484         if(m_pGraphThread)
    00485         {
    00486                 CAMEvent e;
    00487                 m_pGraphThread->PostThreadMessage(CGraphThread::TM_EXIT, 0, (LPARAM)&e);
    00488                 if(!e.Wait(5000))
    00489                 {
    00490                         TRACE(_T("ERROR: Must call TerminateThread() on CMainFrame::m_pGraphThread->m_hThread\n"));
    00491                         TerminateThread(m_pGraphThread->m_hThread, -1);
    00492                 }
    00493         }
    00494
    00495         __super::OnDestroy();
    00496 }
    00497
    00498 void CMainFrame::OnClose()
    00499 {
    00500         m_wndPlaylistBar.SavePlaylist();
    00501
    00502         SaveControlBar(&m_wndSubresyncBar, _T("ToolBars\\Subresync"));
    00503         SaveControlBar(&m_wndPlaylistBar, _T("ToolBars\\Playlist"));
    00504         SaveControlBar(&m_wndCaptureBar, _T("ToolBars\\Capture"));
    00505
    00506         ShowWindow(SW_HIDE);
    00507
    00508         CloseMedia();
    00509
    00510         __super::OnClose();
    00511 }
    00512
    00513 DROPEFFECT CMainFrame::OnDragEnter(COleDataObject* pDataObject, DWORD dwKeyState, CPoint point)
    00514 {
    00515         return DROPEFFECT_NONE;
    00516 }
    00517 DROPEFFECT CMainFrame::OnDragOver(COleDataObject* pDataObject, DWORD dwKeyState, CPoint point)
    00518 {
    00519         UINT CF_URL = RegisterClipboardFormat(_T("UniformResourceLocator"));
    00520         return pDataObject->IsDataAvailable(CF_URL) ? DROPEFFECT_COPY : DROPEFFECT_NONE;
    00521 }
    00522 BOOL CMainFrame::OnDrop(COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point)
    00523 {
    00524         UINT CF_URL = RegisterClipboardFormat(_T("UniformResourceLocator"));
    00525
    00526         BOOL bResult = FALSE;
    00527
    00528         if(pDataObject->IsDataAvailable(CF_URL))
    00529         {
    00530                 FORMATETC fmt = {CF_URL, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
    00531                 if(HGLOBAL hGlobal = pDataObject->GetGlobalData(CF_URL, &fmt))
    00532                 {
    00533                         LPCSTR pText = (LPCSTR)GlobalLock(hGlobal);
    00534                         if(AfxIsValidString(pText))
    00535                         {
    00536                                 CStringA url(pText);
    00537
    00538                                 SetForegroundWindow();
    00539
    00540                                 CList<CString> sl;
    00541                                 sl.AddTail(CString(url));
    00542
    00543                                 if(m_wndPlaylistBar.IsWindowVisible())
    00544                                 {
    00545                                         m_wndPlaylistBar.Append(sl, true);
    00546                                 }
    00547                                 else
    00548                                 {
    00549                                         m_wndPlaylistBar.Open(sl, true);
    00550                                         OpenCurPlaylistItem();
    00551                                 }
    00552
    00553                                 GlobalUnlock(hGlobal);
    00554                                 bResult = TRUE;
    00555                         }
    00556                 }
    00557         }
    00558
    00559         return bResult;
    00560 }
    00561 DROPEFFECT CMainFrame::OnDropEx(COleDataObject* pDataObject, DROPEFFECT dropDefault, DROPEFFECT dropList, CPoint point)
    00562 {
    00563         return (DROPEFFECT)-1;
    00564 }
    00565 void CMainFrame::OnDragLeave()
    00566 {
    00567 }
    00568 DROPEFFECT CMainFrame::OnDragScroll(DWORD dwKeyState, CPoint point)
    00569 {
    00570         return DROPEFFECT_NONE;
    00571 }
    00572
    00573 void CMainFrame::LoadControlBar(CControlBar* pBar, CString section, UINT defDockBarID)
    00574 {
    00575         if(!pBar || section.IsEmpty()) return;
    00576
    00577         CWinApp* pApp = AfxGetApp();
    00578
    00579         UINT nID = pApp->GetProfileInt(section, _T("DockState"), defDockBarID);
    00580
    00581         if(nID != AFX_IDW_DOCKBAR_FLOAT)
    00582         {
    00583                 DockControlBar(pBar, nID);
    00584         }
    00585         else
    00586         {
    00587                 // FIXME
    00588                 CRect r;
    00589                 GetWindowRect(r);
    00590                 CPoint p;
    00591                 p.x = r.left + pApp->GetProfileInt(section, _T("DockPosX"), r.Width());
    00592                 p.y = r.top + pApp->GetProfileInt(section, _T("DockPosY"), 0);
    00593                 FloatControlBar(pBar, p);
    00594         }
    00595
    00596         pBar->ShowWindow(
    00597                 pApp->GetProfileInt(section, _T("Visible"), FALSE) && pBar != &m_wndSubresyncBar && pBar != &m_wndCaptureBar
    00598                 ? SW_SHOW
    00599                 : SW_HIDE);
    00600
    00601         if(pBar->IsKindOf(RUNTIME_CLASS(CSizingControlBar)))
    00602         {
    00603                 ((CSizingControlBar*)(pBar))->LoadState(section + _T("\\State"));
    00604         }
    00605 }
    00606
    00607 void CMainFrame::SaveControlBar(CControlBar* pBar, CString section)
    00608 {
    00609         if(!pBar || section.IsEmpty()) return;
    00610
    00611         CWinApp* pApp = AfxGetApp();
    00612
    00613         pApp->WriteProfileInt(section, _T("Visible"), pBar->IsWindowVisible());
    00614
    00615         if(pBar->IsKindOf(RUNTIME_CLASS(CSizingControlBar)))
    00616                 ((CSizingControlBar*)(pBar))->SaveState(section + _T("\\State"));
    00617
    00618         UINT nID = pBar->GetParent()->GetDlgCtrlID();
    00619
    00620         if(nID == AFX_IDW_DOCKBAR_FLOAT)
    00621         {
    00622 return;//
    00623                 // FIXME
    00624                 CRect r1, r2;
    00625                 GetWindowRect(r1);
    00626                 pBar->GetWindowRect(r2);
    00627                 pApp->WriteProfileInt(section, _T("DockPosX"), r2.left - r1.left);
    00628                 pApp->WriteProfileInt(section, _T("DockPosY"), r2.top - r1.top);
    00629         }
    00630
    00631         pApp->WriteProfileInt(section, _T("DockState"), nID);
    00632
    00633 }
    00634
    00635 LRESULT CMainFrame::OnTaskBarRestart(WPARAM, LPARAM)
    00636 {
    00637         m_fTrayIcon = false;
    00638         ShowTrayIcon(AfxGetAppSettings().fTrayIcon);
    00639
    00640         return 0;
    00641 }
    00642
    00643 LRESULT CMainFrame::OnNotifyIcon(WPARAM wParam, LPARAM lParam)
    00644 {
    00645     if((UINT)wParam != IDR_MAINFRAME)
    00646                 return -1;
    00647
    00648         switch((UINT)lParam)
    00649         {
    00650                 case WM_LBUTTONDOWN:
    00651                         ShowWindow(SW_SHOW);
    00652                         MoveVideoWindow();
    00653                         SetForegroundWindow();
    00654                         break;
    00655
    00656                 case WM_LBUTTONDBLCLK:
    00657                         PostMessage(WM_COMMAND, ID_FILE_OPENMEDIA);
    00658                         break;
    00659
    00660                 case WM_RBUTTONDOWN:
    00661                 {
    00662                         POINT p;
    00663                         GetCursorPos(&p);
    00664                         SetForegroundWindow();
    00665                         m_popupmain.GetSubMenu(0)->TrackPopupMenu(TPM_RIGHTBUTTON|TPM_NOANIMATION, p.x, p.y, this);
    00666                         PostMessage(WM_NULL);
    00667                         break;
    00668                 }
    00669
    00670                 case WM_MOUSEMOVE:
    00671                 {
    00672                         CString str;
    00673                         GetWindowText(str);
    00674                         SetTrayTip(str);
    00675                         break;
    00676                 }
    00677
    00678                 default:
    00679                         break;
    00680         }
    00681
    00682         return 0;
    00683 }
    00684
    00685 void CMainFrame::ShowTrayIcon(bool fShow)
    00686 {
    00687     BOOL bWasVisible = ShowWindow(SW_HIDE);
    00688
    00689         if(fShow)
    00690         {
    00691                 if(!m_fTrayIcon)
    00692                 {
    00693                         NOTIFYICONDATA tnid;
    00694                         tnid.cbSize = sizeof(NOTIFYICONDATA);
    00695                         tnid.hWnd = m_hWnd;
    00696                         tnid.uID = IDR_MAINFRAME;
    00697 //                      tnid.hIcon = (HICON)LoadIcon(AfxGetResourceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME));
    00698                         tnid.hIcon = (HICON)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
    00699                         tnid.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP;
    00700                         tnid.uCallbackMessage = WM_NOTIFYICON;
    00701                         lstrcpyn(tnid.szTip, TEXT("Media Player Classic"), sizeof(tnid.szTip));
    00702                         Shell_NotifyIcon(NIM_ADD, &tnid);
    00703
    00704                         m_fTrayIcon = true;
    00705                 }
    00706         }
    00707         else
    00708         {
    00709                 if(m_fTrayIcon)
    00710                 {
    00711                         NOTIFYICONDATA tnid;
    00712                         tnid.cbSize = sizeof(NOTIFYICONDATA);
    00713                         tnid.hWnd = m_hWnd;
    00714                         tnid.uID = IDR_MAINFRAME;
    00715                         Shell_NotifyIcon(NIM_DELETE, &tnid);
    00716
    00717                         m_fTrayIcon = false;
    00718                 }
    00719         }
    00720
    00721         if(bWasVisible)
    00722                 ShowWindow(SW_SHOW);
    00723 }
    00724
    00725 void CMainFrame::SetTrayTip(CString str)
    00726 {
    00727         NOTIFYICONDATA tnid;
    00728         tnid.cbSize = sizeof(NOTIFYICONDATA);
    00729         tnid.hWnd = m_hWnd;
    00730         tnid.uID = IDR_MAINFRAME;
    00731         tnid.uFlags = NIF_TIP;
    00732         lstrcpyn(tnid.szTip, str, sizeof(tnid.szTip));
    00733         Shell_NotifyIcon(NIM_MODIFY, &tnid);
    00734 }
    00735
    00736 BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
    00737 {
    00738         if(!__super::PreCreateWindow(cs))
    00739                 return FALSE;
    00740
    00741         cs.dwExStyle &= ~WS_EX_CLIENTEDGE;
    00742         cs.lpszClass = MPC_WND_CLASS_NAME; //AfxRegisterWndClass(0);
    00743
    00744         return TRUE;
    00745 }
    00746
    00747 BOOL CMainFrame::PreTranslateMessage(MSG* pMsg)
    00748 {
    00749         if(pMsg->message == WM_KEYDOWN)
    00750         {
    00751 /*              if(m_fShockwaveGraph
    00752                 && (pMsg->wParam == VK_LEFT || pMsg->wParam == VK_RIGHT
    00753                         || pMsg->wParam == VK_UP || pMsg->wParam == VK_DOWN))
    00754                         return FALSE;
    00755 */
    00756                 if(pMsg->wParam == VK_ESCAPE && m_iMediaLoadState == MLS_LOADED && m_fFullScreen)
    00757                 {
    00758                         OnViewFullscreen();
    00759                         PostMessage(WM_COMMAND, ID_PLAY_PAUSE);
    00760                         return TRUE;
    00761                 }
    00762                 else if(pMsg->wParam == VK_ESCAPE && (IsCaptionMenuHidden()))
    00763                 {
    00764                         PostMessage(WM_COMMAND, ID_VIEW_CAPTIONMENU);
    00765                         return TRUE;
    00766                 }
    00767                 else if(pMsg->wParam == VK_LEFT && pAMTuner)
    00768                 {
    00769                         PostMessage(WM_COMMAND, ID_NAVIGATE_SKIPBACK);
    00770                         return TRUE;
    00771                 }
    00772                 else if(pMsg->wParam == VK_RIGHT && pAMTuner)
    00773                 {
    00774                         PostMessage(WM_COMMAND, ID_NAVIGATE_SKIPFORWARD);
    00775                         return TRUE;
    00776                 }
    00777         }
    00778
    00779         return __super::PreTranslateMessage(pMsg);
    00780 }
    00781
    00782 void CMainFrame::RecalcLayout(BOOL bNotify)
    00783 {
    00784         __super::RecalcLayout(bNotify);
    00785
    00786         CRect r;
    00787         GetWindowRect(&r);
    00788         MINMAXINFO mmi;
    00789         memset(&mmi, 0, sizeof(mmi));
    00790         SendMessage(WM_GETMINMAXINFO, 0, (LPARAM)&mmi);
    00791         r |= CRect(r.TopLeft(), CSize(r.Width(), mmi.ptMinTrackSize.y));
    00792         MoveWindow(&r);
    00793 }
    00794
    00796 // CMainFrame diagnostics
    00797
    00798 #ifdef _DEBUG
    00799 void CMainFrame::AssertValid() const
    00800 {
    00801         __super::AssertValid();
    00802 }
    00803
    00804 void CMainFrame::Dump(CDumpContext& dc) const
    00805 {
    00806         __super::Dump(dc);
    00807 }
    00808
    00809 #endif //_DEBUG
    00810
    00812 // CMainFrame message handlers
    00813 void CMainFrame::OnSetFocus(CWnd* pOldWnd)
    00814 {
    00815         SetAlwaysOnTop(AfxGetAppSettings().iOnTop);
    00816
    00817         // forward focus to the view window
    00818         if(IsWindow(m_wndView.m_hWnd))
    00819                 m_wndView.SetFocus();
    00820 }
    00821
    00822 BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
    00823 {
    00824         // let the view have first crack at the command
    00825         if(m_wndView.OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
    00826                 return TRUE;
    00827
    00828         POSITION pos = m_bars.GetHeadPosition();
    00829         while(pos)
    00830         {
    00831                 if(m_bars.GetNext(pos)->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
    00832                         return TRUE;
    00833         }
    00834
    00835         pos = m_dockingbars.GetHeadPosition();
    00836         while(pos)
    00837         {
    00838                 if(m_dockingbars.GetNext(pos)->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
    00839                         return TRUE;
    00840         }
    00841
    00842         // otherwise, do default handling
    00843         return __super::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
    00844 }
    00845
    00846 void CMainFrame::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
    00847 {
    00848         DWORD style = GetStyle();
    00849
    00850         MENUBARINFO mbi;
    00851         memset(&mbi, 0, sizeof(mbi));
    00852         mbi.cbSize = sizeof(mbi);
    00853         ::GetMenuBarInfo(m_hWnd, OBJID_MENU, 0, &mbi);
    00854
    00855         lpMMI->ptMinTrackSize.x = 0;
    00856         if(!IsCaptionMenuHidden())
    00857         {
    00858                 lpMMI->ptMinTrackSize.x = 10;
    00859                 CRect r;
    00860                 for(int i = 0; ::GetMenuItemRect(m_hWnd, mbi.hMenu, i, &r); i++)
    00861                         lpMMI->ptMinTrackSize.x += r.Width();
    00862                 lpMMI->ptMinTrackSize.x = max(DEFCLIENTW, lpMMI->ptMinTrackSize.x);
    00863         }
    00864         if(style&WS_THICKFRAME) lpMMI->ptMinTrackSize.x += GetSystemMetrics((style&WS_CAPTION)?SM_CXSIZEFRAME:SM_CXFIXEDFRAME)*2;
    00865
    00866         memset(&mbi, 0, sizeof(mbi));
    00867         mbi.cbSize = sizeof(mbi);
    00868         ::GetMenuBarInfo(m_hWnd, OBJID_MENU, 0, &mbi);
    00869
    00870         lpMMI->ptMinTrackSize.y = 0;
    00871         if(style&WS_CAPTION) lpMMI->ptMinTrackSize.y += GetSystemMetrics(SM_CYCAPTION);
    00872         if(style&WS_THICKFRAME) lpMMI->ptMinTrackSize.y += GetSystemMetrics((style&WS_CAPTION)?SM_CYSIZEFRAME:SM_CYFIXEDFRAME)*2;
    00873         lpMMI->ptMinTrackSize.y += (mbi.rcBar.bottom - mbi.rcBar.top);
    00874         if(!AfxGetAppSettings().fHideCaptionMenu) lpMMI->ptMinTrackSize.y += 3;
    00875
    00876         POSITION pos = m_bars.GetHeadPosition();
    00877         while(pos)
    00878         {
    00879                 CControlBar* pCB = m_bars.GetNext(pos);
    00880                 if(!IsWindow(pCB->m_hWnd) || !pCB->IsVisible()) continue;
    00881
    00882                 lpMMI->ptMinTrackSize.y += pCB->CalcFixedLayout(TRUE, TRUE).cy;
    00883         }
    00884
    00885         if(IsWindow(m_wndSubresyncBar.m_hWnd) && m_wndSubresyncBar.IsWindowVisible() && !m_wndSubresyncBar.IsFloating())
    00886                 lpMMI->ptMinTrackSize.y += m_wndSubresyncBar.CalcFixedLayout(TRUE, TRUE).cy-2;
    00887
    00888         if(IsWindow(m_wndPlaylistBar.m_hWnd) && m_wndPlaylistBar.IsWindowVisible() && !m_wndPlaylistBar.IsFloating())
    00889                 lpMMI->ptMinTrackSize.y += m_wndPlaylistBar.CalcFixedLayout(TRUE, TRUE).cy-2;
    00890
    00891         if(IsWindow(m_wndCaptureBar.m_hWnd) && m_wndCaptureBar.IsWindowVisible() && !m_wndCaptureBar.IsFloating())
    00892                 lpMMI->ptMinTrackSize.y += m_wndCaptureBar.CalcFixedLayout(TRUE, TRUE).cy-2;
    00893
    00894         __super::OnGetMinMaxInfo(lpMMI);
    00895 }
    00896
    00897 void CMainFrame::OnMove(int x, int y)
    00898 {
    00899         __super::OnMove(x, y);
    00900
    00901         MoveVideoWindow();
    00902
    00903         WINDOWPLACEMENT wp;
    00904         GetWindowPlacement(&wp);
    00905         if(!m_fFullScreen && wp.flags != WPF_RESTORETOMAXIMIZED && wp.showCmd != SW_SHOWMINIMIZED)
    00906                 GetWindowRect(AfxGetAppSettings().rcLastWindowPos);
    00907 }
    00908
    00909 void CMainFrame::OnSize(UINT nType, int cx, int cy)
    00910 {
    00911         __super::OnSize(nType, cx, cy);
    00912
    00913         if(nType == SIZE_RESTORED && m_fTrayIcon)
    00914         {
    00915                 ShowWindow(SW_SHOW);
    00916         }
    00917
    00918         if(!m_fFullScreen)
    00919         {
    00920                 AppSettings& s = AfxGetAppSettings();
    00921                 if(nType != SIZE_MAXIMIZED && nType != SIZE_MINIMIZED)
    00922                         GetWindowRect(s.rcLastWindowPos);
    00923                 s.lastWindowType = nType;
    00924         }
    00925 }
    00926
    00927 void CMainFrame::OnSizing(UINT fwSide, LPRECT pRect)
    00928 {
    00929         __super::OnSizing(fwSide, pRect);
    00930
    00931         AppSettings& s = AfxGetAppSettings();
    00932
    00933         bool fCtrl = !!(GetAsyncKeyState(VK_CONTROL)&0x80000000);
    00934
    00935         if(m_iMediaLoadState != MLS_LOADED || m_fFullScreen
    00936         || s.iDefaultVideoSize == DVS_STRETCH
    00937         || (fCtrl ^ s.fFreeWindowResizing))
    00938                 return;
    00939
    00940         CSize wsize(pRect->right - pRect->left, pRect->bottom - pRect->top);
    00941         CSize vsize = GetVideoSize();
    00942         CSize fsize(0, 0);
    00943
    00944         if(!vsize.cx || !vsize.cy)
    00945                 return;
    00946
    00947         // TODO
    00948         {
    00949                 DWORD style = GetStyle();
    00950
    00951                 MENUBARINFO mbi;
    00952                 memset(&mbi, 0, sizeof(mbi));
    00953                 mbi.cbSize = sizeof(mbi);
    00954                 ::GetMenuBarInfo(m_hWnd, OBJID_MENU, 0, &mbi);
    00955
    00956                 fsize.cx += GetSystemMetrics((style&WS_CAPTION)?SM_CXSIZEFRAME:SM_CXFIXEDFRAME)*2;
    00957
    00958                 if(style&WS_CAPTION) fsize.cy += GetSystemMetrics(SM_CYCAPTION);
    00959                 if(style&WS_THICKFRAME) fsize.cy += GetSystemMetrics((style&WS_CAPTION)?SM_CYSIZEFRAME:SM_CYFIXEDFRAME)*2;
    00960                 fsize.cy += mbi.rcBar.bottom - mbi.rcBar.top;
    00961                 if(!AfxGetAppSettings().fHideCaptionMenu) fsize.cy += 3;
    00962
    00963                 POSITION pos = m_bars.GetHeadPosition();
    00964                 while(pos)
    00965                 {
    00966                         CControlBar* pCB = m_bars.GetNext(pos);
    00967                         if(IsWindow(pCB->m_hWnd) && pCB->IsVisible())
    00968                                 fsize.cy += pCB->CalcFixedLayout(TRUE, TRUE).cy;
    00969                 }
    00970
    00971                 if(IsWindow(m_wndSubresyncBar.m_hWnd) && m_wndSubresyncBar.IsWindowVisible())
    00972                 {
    00973                         if(m_wndSubresyncBar.IsHorzDocked())
    00974                                 fsize.cy += m_wndSubresyncBar.CalcFixedLayout(TRUE, TRUE).cy-2;
    00975                         else if(m_wndSubresyncBar.IsVertDocked())
    00976                                 fsize.cx += m_wndSubresyncBar.CalcFixedLayout(TRUE, FALSE).cx;
    00977                 }
    00978
    00979                 if(IsWindow(m_wndPlaylistBar.m_hWnd) && m_wndPlaylistBar.IsWindowVisible())
    00980                 {
    00981                         if(m_wndPlaylistBar.IsHorzDocked())
    00982                                 fsize.cy += m_wndPlaylistBar.CalcFixedLayout(TRUE, TRUE).cy-2;
    00983                         else if(m_wndPlaylistBar.IsVertDocked())
    00984                                 fsize.cx += m_wndPlaylistBar.CalcFixedLayout(TRUE, FALSE).cx;
    00985                 }
    00986
    00987                 if(IsWindow(m_wndCaptureBar.m_hWnd) && m_wndCaptureBar.IsWindowVisible())
    00988                 {
    00989                         if(m_wndCaptureBar.IsHorzDocked())
    00990                                 fsize.cy += m_wndCaptureBar.CalcFixedLayout(TRUE, TRUE).cy-2;
    00991                         else if(m_wndCaptureBar.IsVertDocked())
    00992                                 fsize.cx += m_wndCaptureBar.CalcFixedLayout(TRUE, FALSE).cx;
    00993                 }
    00994         }
    00995
    00996         wsize -= fsize;
    00997
    00998         bool fWider = wsize.cy < wsize.cx;
    00999
    01000         wsize.SetSize(
    01001                 wsize.cy * vsize.cx / vsize.cy,
    01002                 wsize.cx * vsize.cy / vsize.cx);
    01003
    01004         wsize += fsize;
    01005
    01006         if(fwSide == WMSZ_TOP || fwSide == WMSZ_BOTTOM || !fWider && (fwSide == WMSZ_TOPRIGHT || fwSide == WMSZ_BOTTOMRIGHT))
    01007         {
    01008                 pRect->right = pRect->left + wsize.cx;
    01009         }
    01010         else if(fwSide == WMSZ_LEFT || fwSide == WMSZ_RIGHT || fWider && (fwSide == WMSZ_BOTTOMLEFT || fwSide == WMSZ_BOTTOMRIGHT))
    01011         {
    01012                 pRect->bottom = pRect->top + wsize.cy;
    01013         }
    01014         else if(!fWider && (fwSide == WMSZ_TOPLEFT || fwSide == WMSZ_BOTTOMLEFT))
    01015         {
    01016                 pRect->left = pRect->right - wsize.cx;
    01017         }
    01018         else if(fWider && (fwSide == WMSZ_TOPLEFT || fwSide == WMSZ_TOPRIGHT))
    01019         {
    01020                 pRect->top = pRect->bottom - wsize.cy;
    01021         }
    01022 }
    01023
    01024 void CMainFrame::OnDisplayChange() // untested, not sure if it's working...
    01025 {
    01026         TRACE(_T("*** CMainFrame::OnDisplayChange()\n"));
    01027 /*
    01028         if(m_iMediaLoadState == MLS_LOADED && m_pCAP)
    01029                 m_pCAP->OnDisplayChange();
    01030 */
    01031 }
    01032
    01033 void CMainFrame::OnSysCommand(UINT nID, LPARAM lParam)
    01034 {
    01035         if((nID & 0xFFF0) == SC_SCREENSAVE)
    01036         {
    01037                 TRACE(_T("SC_SCREENSAVE, nID = %d, lParam = %d\n"), nID, lParam);
    01038         }
    01039         else if((nID & 0xFFF0) == SC_MINIMIZE && m_fTrayIcon)
    01040         {
    01041                 ShowWindow(SW_HIDE);
    01042                 return;
    01043         }
    01044
    01045         __super::OnSysCommand(nID, lParam);
    01046 }
    01047
    01048 void CMainFrame::OnActivateApp(BOOL bActive, DWORD dwThreadID)
    01049 {
    01050         __super::OnActivateApp(bActive, dwThreadID);
    01051
    01052         MONITORINFO mi;
    01053         mi.cbSize = sizeof(MONITORINFO);
    01054         GetMonitorInfo(MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST), &mi);
    01055
    01056         if(m_iMediaLoadState == MLS_LOADED && m_fFullScreen && !bActive && (mi.dwFlags&MONITORINFOF_PRIMARY))
    01057         {
    01058                 OnViewFullscreen();
    01059         }
    01060 }
    01061
    01062 LRESULT CMainFrame::OnAppCommand(WPARAM wParam, LPARAM lParam)
    01063 {
    01064         UINT cmd  = GET_APPCOMMAND_LPARAM(lParam);
    01065         UINT uDevice = GET_DEVICE_LPARAM(lParam);
    01066         UINT dwKeys = GET_KEYSTATE_LPARAM(lParam);
    01067
    01068         if(uDevice != FAPPCOMMAND_OEM)
    01069         {
    01070                 AppSettings& s = AfxGetAppSettings();
    01071
    01072                 BOOL fRet = FALSE;
    01073
    01074                 POSITION pos = s.wmcmds.GetHeadPosition();
    01075                 while(pos)
    01076                 {
    01077                         wmcmd& wc = s.wmcmds.GetNext(pos);
    01078                         if(wc.appcmd == cmd && TRUE == SendMessage(WM_COMMAND, wc.cmd))
    01079                                 fRet = TRUE;
    01080                 }
    01081
    01082                 if(fRet) return TRUE;
    01083         }
    01084
    01085         return Default();
    01086 }
    01087
    01088 void CMainFrame::OnTimer(UINT nIDEvent)
    01089 {
    01090         if(nIDEvent == TIMER_STREAMPOSPOLLER && m_iMediaLoadState == MLS_LOADED)
    01091         {
    01092                 REFERENCE_TIME rtNow = 0, rtDur = 0;
    01093
    01094                 if(m_iPlaybackMode == PM_FILE)
    01095                 {
    01096                         pMS->GetCurrentPosition(&rtNow);
    01097                         pMS->GetDuration(&rtDur);
    01098
    01099                         if(m_rtDurationOverride >= 0) rtDur = m_rtDurationOverride;
    01100
    01101                         m_wndSeekBar.Enable(rtDur > 0);
    01102                         m_wndSeekBar.SetRange(0, rtDur);
    01103                         m_wndSeekBar.SetPos(rtNow);
    01104                 }
    01105                 else if(m_iPlaybackMode == PM_CAPTURE)
    01106                 {
    01107                         if(m_fCapturing && m_wndCaptureBar.m_capdlg.m_pMux)
    01108                         {
    01109                                 CComQIPtr<IMediaSeeking> pMuxMS = m_wndCaptureBar.m_capdlg.m_pMux;
    01110                                 if(!pMuxMS || FAILED(pMuxMS->GetCurrentPosition(&rtNow))) rtNow = 0;
    01111                         }
    01112
    01113                         if(m_rtDurationOverride >= 0) rtDur = m_rtDurationOverride;
    01114
    01115                         m_wndSeekBar.Enable(false);
    01116                         m_wndSeekBar.SetRange(0, rtDur);
    01117                         m_wndSeekBar.SetPos(rtNow);
    01118 /*
    01119                         if(m_fCapturing)
    01120                         {
    01121                                 if(rtNow > 10000i64*1000*60*60*3)
    01122                                 {
    01123                                         m_wndCaptureBar.m_capdlg.OnRecord();
    01124                                 }
    01125                         }
    01126 */
    01127                 }
    01128
    01129                 if(m_pCAP && m_iPlaybackMode != PM_FILE) m_pCAP->SetTime(/*rtNow*/m_wndSeekBar.GetPos());
    01130         }
    01131         else if(nIDEvent == TIMER_STREAMPOSPOLLER2 && m_iMediaLoadState == MLS_LOADED)
    01132         {
    01133                 __int64 start, stop, pos;
    01134                 m_wndSeekBar.GetRange(start, stop);
    01135                 pos = m_wndSeekBar.GetPosReal();
    01136
    01137                 GUID tf;
    01138                 pMS->GetTimeFormat(&tf);
    01139
    01140                 if(m_iPlaybackMode == PM_CAPTURE && !m_fCapturing)
    01141                 {
    01142                         CString str = _T("Live");
    01143
    01144                         long lChannel = 0, lVivSub = 0, lAudSub = 0;
    01145                         if(pAMTuner
    01146                         && m_wndCaptureBar.m_capdlg.IsTunerActive()
    01147                         && SUCCEEDED(pAMTuner->get_Channel(&lChannel, &lVivSub, &lAudSub)))
    01148                         {
    01149                                 CString ch;
    01150                                 ch.Format(_T(" (ch%d)"), lChannel);
    01151                                 str += ch;
    01152                         }
    01153
    01154                         m_wndStatusBar.SetStatusTimer(str);
    01155                 }
    01156                 else
    01157                 {
    01158                         m_wndStatusBar.SetStatusTimer(pos, stop, !!m_wndSubresyncBar.IsWindowVisible(), &tf);
    01159                 }
    01160
    01161                 m_wndSubresyncBar.SetTime(pos);
    01162
    01163                 if(m_pCAP && GetMediaState() == State_Paused) m_pCAP->Paint(true);
    01164         }
    01165         else if(nIDEvent == TIMER_FULLSCREENCONTROLBARHIDER)
    01166         {
    01167                 CPoint p;
    01168                 GetCursorPos(&p);
    01169
    01170                 CRect r;
    01171                 GetWindowRect(r);
    01172                 bool fCursorOutside = !r.PtInRect(p);
    01173
    01174                 CWnd* pWnd = WindowFromPoint(p);
    01175                 if(pWnd && (m_wndView == *pWnd || m_wndView.IsChild(pWnd) || fCursorOutside))
    01176                 {
    01177                         if(AfxGetAppSettings().nShowBarsWhenFullScreenTimeOut >= 0)
    01178                                 ShowControls(CS_NONE, false);
    01179                 }
    01180         }
    01181         else if(nIDEvent == TIMER_FULLSCREENMOUSEHIDER)
    01182         {
    01183                 CPoint p;
    01184                 GetCursorPos(&p);
    01185
    01186                 CRect r;
    01187                 GetWindowRect(r);
    01188                 bool fCursorOutside = !r.PtInRect(p);
    01189
    01190                 CWnd* pWnd = WindowFromPoint(p);
    01191                 if(pWnd && (m_wndView == *pWnd || m_wndView.IsChild(pWnd) || fCursorOutside))
    01192                 {
    01193                         m_fHideCursor = true;
    01194                         SetCursor(NULL);
    01195                 }
    01196         }
    01197         else if(nIDEvent == TIMER_STATS)
    01198         {
    01199                 if(pQP)
    01200                 {
    01201                         CString rate;
    01202                         if(m_iSpeedLevel >= -11 && m_iSpeedLevel <= 3 && m_iSpeedLevel != -4)
    01203                         {
    01204                                 CString speeds[] = {_T("1/8"),_T("1/4"),_T("1/2"),_T("1"),_T("2"),_T("4"),_T("8")};
    01205                                 rate = speeds[(m_iSpeedLevel >= -3 ? m_iSpeedLevel : (-m_iSpeedLevel - 8)) + 3];
    01206                                 if(m_iSpeedLevel < -4) rate = _T("-") + rate;
    01207                                 if(!rate.IsEmpty()) rate = _T("(") + rate + _T("X)");
    01208                         }
    01209
    01210                         CString info;
    01211                         int val;
    01212
    01213                         pQP->get_AvgFrameRate(&val);
    01214                         info.Format(_T("%d.%02d %s"), val/100, val%100, rate);
    01215                         m_wndStatsBar.SetLine(_T("Frame-rate"), info);
    01216
    01217                         int avg, dev;
    01218                         pQP->get_AvgSyncOffset(&avg);
    01219                         pQP->get_DevSyncOffset(&dev);
    01220                         info.Format(_T("avg: %d ms, dev: %d ms"), avg, dev);
    01221                         m_wndStatsBar.SetLine(_T("Sync Offset"), info);
    01222
    01223                         int drawn, dropped;
    01224                         pQP->get_FramesDrawn(&drawn);
    01225                         pQP->get_FramesDroppedInRenderer(&dropped);
    01226                         info.Format(_T("drawn: %d, dropped: %d"), drawn, dropped);
    01227                         m_wndStatsBar.SetLine(_T("Frames"), info);
    01228
    01229                         pQP->get_Jitter(&val);
    01230                         info.Format(_T("%d ms"), val);
    01231                         m_wndStatsBar.SetLine(_T("Jitter"), info);
    01232                 }
    01233
    01234                 if(pBI)
    01235                 {
    01236                         CList<CString> sl;
    01237
    01238                         for(int i = 0, j = pBI->GetCount(); i < j; i++)
    01239                         {
    01240                                 int samples, size;
    01241                                 if(S_OK == pBI->GetStatus(i, samples, size))
    01242                                 {
    01243                                         CString str;
    01244                                         str.Format(_T("[%d]: %03d/%d KB"), i, samples, size / 1024);
    01245                                         sl.AddTail(str);
    01246                                 }
    01247                         }
    01248
    01249                         if(!sl.IsEmpty())
    01250                         {
    01251                                 CString str;
    01252                                 str.Format(_T("%s (p%d)"), Implode(sl, ' '), pBI->GetPriority());
    01253
    01254                                 m_wndStatsBar.SetLine(_T("Buffers"), str);
    01255                         }
    01256                 }
    01257
    01258                 CInterfaceList<IBitRateInfo> pBRIs;
    01259
    01260                 BeginEnumFilters(pGB, pEF, pBF)
    01261                 {
    01262                         BeginEnumPins(pBF, pEP, pPin)
    01263                         {
    01264                                 if(CComQIPtr<IBitRateInfo> pBRI = pPin)
    01265                                 {
    01266                                         pBRIs.AddTail(pBRI);
    01267                                 }
    01268                         }
    01269                         EndEnumPins
    01270
    01271                         if(!pBRIs.IsEmpty())
    01272                         {
    01273                                 CList<CString> sl;
    01274
    01275                                 POSITION pos = pBRIs.GetHeadPosition();
    01276                                 for(int i = 0; pos; i++)
    01277                                 {
    01278                                         IBitRateInfo* pBRI = pBRIs.GetNext(pos);
    01279
    01280                                         DWORD cur = pBRI->GetCurrentBitRate() / 1000;
    01281                                         DWORD avg = pBRI->GetAverageBitRate() / 1000;
    01282
    01283                                         if(avg == 0) continue;
    01284
    01285                                         CString str;
    01286                                         if(cur != avg) str.Format(_T("[%d]: %d/%d Kb/s"), i, avg, cur);
    01287                                         else str.Format(_T("[%d]: %d Kb/s"), i, avg);
    01288                                         sl.AddTail(str);
    01289                                 }
    01290
    01291                                 if(!sl.IsEmpty())
    01292                                 {
    01293                                         m_wndStatsBar.SetLine(_T("Bitrate"), Implode(sl, ' ') + _T(" (avg/cur)"));
    01294                                 }
    01295
    01296                                 break;
    01297                         }
    01298                 }
    01299                 EndEnumFilters
    01300
    01301                 if(m_iPlaybackMode == PM_FILE)
    01302                 {
    01303                         SetupChapters();
    01304                 }
    01305
    01306                 if(m_iPlaybackMode == PM_DVD) // we also use this timer to update the info panel for dvd playback
    01307                 {
    01308                         ULONG ulAvailable, ulCurrent;
    01309
    01310                         // Domain
    01311
    01312                         CString Domain('-');
    01313
    01314                         DVD_DOMAIN dom;
    01315
    01316                         if(SUCCEEDED(pDVDI->GetCurrentDomain(&dom)))
    01317                         {
    01318                                 switch(dom)
    01319                                 {
    01320                                 case DVD_DOMAIN_FirstPlay: Domain = _T("First Play"); break;
    01321                                 case DVD_DOMAIN_VideoManagerMenu: Domain = _T("Video Manager Menu"); break;
    01322                                 case DVD_DOMAIN_VideoTitleSetMenu: Domain = _T("Video Title Set Menu"); break;
    01323                                 case DVD_DOMAIN_Title: Domain = _T("Title"); break;
    01324                                 case DVD_DOMAIN_Stop: Domain = _T("Stop"); break;
    01325                                 default: Domain = _T("-"); break;
    01326                                 }
    01327                         }
    01328
    01329                         m_wndInfoBar.SetLine(_T("Domain"), Domain);
    01330
    01331                         // Location
    01332
    01333                         CString Location('-');
    01334
    01335                         DVD_PLAYBACK_LOCATION2 loc;
    01336                         ULONG ulNumOfVolumes, ulVolume;
    01337                         DVD_DISC_SIDE Side;
    01338                         ULONG ulNumOfTitles;
    01339                         ULONG ulNumOfChapters;
    01340
    01341                         if(SUCCEEDED(pDVDI->GetCurrentLocation(&loc))
    01342                         && SUCCEEDED(pDVDI->GetNumberOfChapters(loc.TitleNum, &ulNumOfChapters))
    01343                         && SUCCEEDED(pDVDI->GetDVDVolumeInfo(&ulNumOfVolumes, &ulVolume, &Side, &ulNumOfTitles)))
    01344                         {
    01345                                 Location.Format(_T("Volume: %02d/%02d, Title: %02d/%02d, Chapter: %02d/%02d"),
    01346                                         ulVolume, ulNumOfVolumes,
    01347                                         loc.TitleNum, ulNumOfTitles,
    01348                                         loc.ChapterNum, ulNumOfChapters);
    01349                         }
    01350
    01351                         m_wndInfoBar.SetLine(_T("Location"), Location);
    01352
    01353                         // Video
    01354
    01355                         CString Video('-');
    01356
    01357                         DVD_VideoAttributes VATR;
    01358
    01359                         if(SUCCEEDED(pDVDI->GetCurrentAngle(&ulAvailable, &ulCurrent))
    01360                         && SUCCEEDED(pDVDI->GetCurrentVideoAttributes(&VATR)))
    01361                         {
    01362                                 Video.Format(_T("Angle: %02d/%02d, %dx%d %dHz %d:%d"),
    01363                                         ulAvailable, ulCurrent,
    01364                                         VATR.ulSourceResolutionX, VATR.ulSourceResolutionY, VATR.ulFrameRate,
    01365                                         VATR.ulAspectX, VATR.ulAspectY);
    01366                         }
    01367
    01368                         m_wndInfoBar.SetLine(_T("Video"), Video);
    01369
    01370                         // Audio
    01371
    01372                         CString Audio('-');
    01373
    01374                         DVD_AudioAttributes AATR;
    01375
    01376                         if(SUCCEEDED(pDVDI->GetCurrentAudio(&ulAvailable, &ulCurrent))
    01377                         && SUCCEEDED(pDVDI->GetAudioAttributes(ulCurrent, &AATR)))
    01378                         {
    01379                                 CString lang;
    01380                                 int len = GetLocaleInfo(AATR.Language, LOCALE_SENGLANGUAGE, lang.GetBuffer(64), 64);
    01381                                 lang.ReleaseBufferSetLength(max(len-1, 0));
    01382
    01383                                 switch(AATR.LanguageExtension)
    01384                                 {
    01385                                 case DVD_AUD_EXT_NotSpecified:
    01386                                 default: break;
    01387                                 case DVD_AUD_EXT_Captions: lang += _T(" (Captions)"); break;
    01388                                 case DVD_AUD_EXT_VisuallyImpaired: lang += _T(" (Visually Impaired)"); break;
    01389                                 case DVD_AUD_EXT_DirectorComments1: lang += _T(" (Director Comments 1)"); break;
    01390                                 case DVD_AUD_EXT_DirectorComments2: lang += _T(" (Director Comments 2)"); break;
    01391                                 }
    01392
    01393                                 CString format;
    01394                                 switch(AATR.AudioFormat)
    01395                                 {
    01396                                 case DVD_AudioFormat_AC3: format = _T("AC3"); break;
    01397                                 case DVD_AudioFormat_MPEG1:
    01398                                 case DVD_AudioFormat_MPEG1_DRC: format = _T("MPEG1"); break;
    01399                                 case DVD_AudioFormat_MPEG2:
    01400                                 case DVD_AudioFormat_MPEG2_DRC: format = _T("MPEG2"); break;
    01401                                 case DVD_AudioFormat_LPCM: format = _T("LPCM"); break;
    01402                                 case DVD_AudioFormat_DTS: format = _T("DTS"); break;
    01403                                 case DVD_AudioFormat_SDDS: format = _T("SDDS"); break;
    01404                                 case DVD_AudioFormat_Other:
    01405                                 default: format = _T("Unknown format"); break;
    01406                                 }
    01407
    01408                                 Audio.Format(_T("%s, %s %dHz %dbits %d channel(s)"),
    01409                                         lang,
    01410                                         format,
    01411                                         AATR.dwFrequency,
    01412                                         AATR.bQuantization,
    01413                                         AATR.bNumberOfChannels);
    01414
    01415                                 m_wndStatusBar.SetStatusBitmap(
    01416                                         AATR.bNumberOfChannels == 1 ? IDB_MONO
    01417                                         : AATR.bNumberOfChannels >= 2 ? IDB_STEREO
    01418                                         : IDB_NOAUDIO);
    01419                         }
    01420
    01421                         m_wndInfoBar.SetLine(_T("Audio"), Audio);
    01422
    01423                         // Subtitles
    01424
    01425                         CString Subtitles('-');
    01426
    01427                         BOOL bIsDisabled;
    01428                         DVD_SubpictureAttributes SATR;
    01429
    01430                         if(SUCCEEDED(pDVDI->GetCurrentSubpicture(&ulAvailable, &ulCurrent, &bIsDisabled))
    01431                         && SUCCEEDED(pDVDI->GetSubpictureAttributes(ulCurrent, &SATR)))
    01432                         {
    01433                                 CString lang;
    01434                                 int len = GetLocaleInfo(SATR.Language, LOCALE_SENGLANGUAGE, lang.GetBuffer(64), 64);
    01435                                 lang.ReleaseBufferSetLength(max(len-1, 0));
    01436
    01437                                 switch(SATR.LanguageExtension)
    01438                                 {
    01439                                 case DVD_SP_EXT_NotSpecified:
    01440                                 default: break;
    01441                                 case DVD_SP_EXT_Caption_Normal: lang += _T(""); break;
    01442                                 case DVD_SP_EXT_Caption_Big: lang += _T(" (Big)"); break;
    01443                                 case DVD_SP_EXT_Caption_Children: lang += _T(" (Children)"); break;
    01444                                 case DVD_SP_EXT_CC_Normal: lang += _T(" (CC)"); break;
    01445                                 case DVD_SP_EXT_CC_Big: lang += _T(" (CC Big)"); break;
    01446                                 case DVD_SP_EXT_CC_Children: lang += _T(" (CC Children)"); break;
    01447                                 case DVD_SP_EXT_Forced: lang += _T(" (Forced)"); break;
    01448                                 case DVD_SP_EXT_DirectorComments_Normal: lang += _T(" (Director Comments)"); break;
    01449                                 case DVD_SP_EXT_DirectorComments_Big: lang += _T(" (Director Comments, Big)"); break;
    01450                                 case DVD_SP_EXT_DirectorComments_Children: lang += _T(" (Director Comments, Children)"); break;
    01451                                 }
    01452
    01453                                 if(bIsDisabled) lang = _T("-");
    01454
    01455                                 Subtitles.Format(_T("%s"),
    01456                                         lang);
    01457                         }
    01458
    01459                         m_wndInfoBar.SetLine(_T("Subtitles"), Subtitles);
    01460                 }
    01461
    01462                 if(GetMediaState() == State_Running)
    01463                 {
    01464                         UINT fSaverActive = 0;
    01465                         if(SystemParametersInfo(SPI_GETSCREENSAVEACTIVE, 0, (PVOID)&fSaverActive, 0))
    01466                         {
    01467                                 SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, 0, 0, SPIF_SENDWININICHANGE); // this might not be needed at all...
    01468                                 SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, fSaverActive, 0, SPIF_SENDWININICHANGE);
    01469                         }
    01470
    01471                         fSaverActive = 0;
    01472                         if(SystemParametersInfo(SPI_GETPOWEROFFACTIVE, 0, (PVOID)&fSaverActive, 0))
    01473                         {
    01474                                 SystemParametersInfo(SPI_SETPOWEROFFACTIVE, 0, 0, SPIF_SENDWININICHANGE); // this might not be needed at all...
    01475                                 SystemParametersInfo(SPI_SETPOWEROFFACTIVE, fSaverActive, 0, SPIF_SENDWININICHANGE);
    01476                         }
    01477                 }
    01478         }
    01479         else if(nIDEvent == TIMER_STATUSERASER)
    01480         {
    01481                 KillTimer(TIMER_STATUSERASER);
    01482                 m_playingmsg.Empty();
    01483         }
    01484
    01485         __super::OnTimer(nIDEvent);
    01486 }
    01487
    01488 static bool SetShutdownPrivilege()
    01489 {
    01490    HANDLE hToken;
    01491    TOKEN_PRIVILEGES tkp;
    01492
    01493    // Get a token for this process.
    01494
    01495    if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
    01496            return(false);
    01497
    01498    // Get the LUID for the shutdown privilege.
    01499
    01500    LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
    01501
    01502    tkp.PrivilegeCount = 1;  // one privilege to set
    01503    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    01504
    01505    // Get the shutdown privilege for this process.
    01506
    01507    AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
    01508
    01509    if(GetLastError() != ERROR_SUCCESS)
    01510            return false;
    01511
    01512    return true;
    01513 }
    01514
    01515 bool CMainFrame::DoAfterPlaybackEvent()
    01516 {
    01517         AppSettings& s = AfxGetAppSettings();
    01518
    01519         bool fExit = false;
    01520
    01521         if(s.nCLSwitches&CLSW_CLOSE)
    01522         {
    01523                 fExit = true;
    01524         }
    01525
    01526         if(s.nCLSwitches&CLSW_STANDBY)
    01527         {
    01528                 SetShutdownPrivilege();
    01529                 SetSystemPowerState(TRUE, TRUE);
    01530                 fExit = true; // TODO: unless the app closes, it will call standby or hibernate once again forever, how to avoid that?
    01531         }
    01532         else if(s.nCLSwitches&CLSW_HIBERNATE)
    01533         {
    01534                 SetShutdownPrivilege();
    01535                 SetSystemPowerState(FALSE, TRUE);
    01536                 fExit = true; // TODO: unless the app closes, it will call standby or hibernate once again forever, how to avoid that?
    01537         }
    01538         else if(s.nCLSwitches&CLSW_SHUTDOWN)
    01539         {
    01540                 SetShutdownPrivilege();
    01541                 ExitWindowsEx(EWX_SHUTDOWN|EWX_POWEROFF|EWX_FORCEIFHUNG, 0);
    01542                 fExit = true;
    01543         }
    01544         else if(s.nCLSwitches&CLSW_LOGOFF)
    01545         {
    01546                 SetShutdownPrivilege();
    01547                 ExitWindowsEx(EWX_LOGOFF|EWX_FORCEIFHUNG, 0);
    01548                 fExit = true;
    01549         }
    01550
    01551         if(!fExit) return false;
    01552
    01553         SendMessage(WM_COMMAND, ID_FILE_EXIT);
    01554
    01555         return true;
    01556 }
    01557
    01558 //
    01559 // our WM_GRAPHNOTIFY handler
    01560 //
    01561 #include <comdef.h>
    01562 LRESULT CMainFrame::OnGraphNotify(WPARAM wParam, LPARAM lParam)
    01563 {
    01564     HRESULT hr = S_OK;
    01565
    01566         LONG evCode, evParam1, evParam2;
    01567     while(pME && SUCCEEDED(pME->GetEvent(&evCode, (LONG_PTR*)&evParam1, (LONG_PTR*)&evParam2, 0)))
    01568     {
    01569                 CString str;
    01570
    01571                 if(m_fCustomGraph)
    01572                 {
    01573                         if(EC_BG_ERROR == evCode)
    01574                         {
    01575                                 str = CString((char*)evParam1);
    01576                         }
    01577                 }
    01578
    01579                 hr = pME->FreeEventParams(evCode, evParam1, evParam2);
    01580
    01581         if(EC_COMPLETE == evCode)
    01582         {
    01583                         AppSettings& s = AfxGetAppSettings();
    01584
    01585                         if(m_wndPlaylistBar.GetCount() <= 1)
    01586                         {
    01587                                 m_nLoops++;
    01588
    01589                                 if(DoAfterPlaybackEvent()) return hr;
    01590
    01591                                 if(s.fLoopForever || m_nLoops < s.nLoops)
    01592                                 {
    01593                                         if(GetMediaState() == State_Stopped)
    01594                                         {
    01595                                                 SendMessage(WM_COMMAND, ID_PLAY_PLAY);
    01596                                         }
    01597                                         else
    01598                                         {
    01599                                                 LONGLONG pos = 0;
    01600                                                 pMS->SetPositions(&pos, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning);
    01601
    01602                                                 if(GetMediaState() == State_Paused)
    01603                                                 {
    01604                                                         SendMessage(WM_COMMAND, ID_PLAY_PLAY);
    01605                                                 }
    01606                                         }
    01607                                 }
    01608                                 else
    01609                                 {
    01610                                         if(s.fRewind) SendMessage(WM_COMMAND, ID_PLAY_STOP);
    01611                                         else m_fEndOfStream = true;
    01612                                         SendMessage(WM_COMMAND, ID_PLAY_PAUSE);
    01613
    01614                                         if(m_fFullScreen && s.fExitFullScreenAtTheEnd)
    01615                                                 OnViewFullscreen();
    01616                                 }
    01617                         }
    01618                         else if(m_wndPlaylistBar.GetCount() > 1)
    01619                         {
    01620                                 if(m_wndPlaylistBar.IsAtEnd())
    01621                                 {
    01622                                         if(DoAfterPlaybackEvent()) return hr;
    01623
    01624                                         m_nLoops++;
    01625                                 }
    01626
    01627                                 if(s.fLoopForever || m_nLoops < s.nLoops)
    01628                                 {
    01629                                         int nLoops = m_nLoops;
    01630                                         PostMessage(WM_COMMAND, ID_NAVIGATE_SKIPFORWARD);
    01631                                         m_nLoops = nLoops;
    01632                                 }
    01633                                 else
    01634                                 {
    01635                                         if(m_fFullScreen && s.fExitFullScreenAtTheEnd)
    01636                                                 OnViewFullscreen();
    01637
    01638                                         if(s.fRewind)
    01639                                         {
    01640                                                 AfxGetAppSettings().nCLSwitches |= CLSW_OPEN; // HACK
    01641                                                 PostMessage(WM_COMMAND, ID_NAVIGATE_SKIPFORWARD);
    01642                                         }
    01643                                         else
    01644                                         {
    01645                                                 m_fEndOfStream = true;
    01646                                                 PostMessage(WM_COMMAND, ID_PLAY_PAUSE);
    01647                                         }
    01648                                 }
    01649                         }
    01650         }
    01651                 else if(EC_ERRORABORT == evCode)
    01652                 {
    01653                         TRACE(_T("EC_ERRORABORT, hr = %08x\n"), (HRESULT)evParam1);
    01654 //                      SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
    01655 //                      m_closingmsg = _com_error((HRESULT)evParam1).ErrorMessage();
    01656                 }
    01657                 else if(EC_REPAINT == evCode)
    01658                 {
    01659                         TRACE(_T("EC_REPAINT\n"));
    01660                 }
    01661                 else if(EC_BUFFERING_DATA == evCode)
    01662                 {
    01663                         TRACE(_T("EC_BUFFERING_DATA, %d, %d\n"), (HRESULT)evParam1, evParam2);
    01664
    01665                         m_fBuffering = ((HRESULT)evParam1 != S_OK);
    01666                 }
    01667                 else if(EC_STEP_COMPLETE == evCode)
    01668                 {
    01669                         if(m_fFrameSteppingActive)
    01670                         {
    01671                                 m_fFrameSteppingActive = false;
    01672                                 pBA->put_Volume(m_VolumeBeforeFrameStepping);
    01673                         }
    01674                 }
    01675                 else if(EC_DEVICE_LOST == evCode)
    01676                 {
    01677                         CComQIPtr<IBaseFilter> pBF;
    01678                         if(m_iPlaybackMode == PM_CAPTURE
    01679                         && (!pVidCap && pVidCap == (pBF = (IUnknown*)evParam1)
    01680                                 || !pAudCap && pAudCap == (pBF = (IUnknown*)evParam1))
    01681                         && evParam2 == 0)
    01682                         {
    01683                                 SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
    01684                         }
    01685                 }
    01686                 else if(EC_DVD_TITLE_CHANGE == evCode)
    01687                 {
    01688                         if(m_iPlaybackMode == PM_FILE)
    01689                                 SetupChapters();
    01690                 }
    01691                 else if(EC_DVD_DOMAIN_CHANGE == evCode)
    01692                 {
    01693                         m_iDVDDomain = (DVD_DOMAIN)evParam1;
    01694                         TRACE(_T("EC_DVD_DOMAIN_CHANGE %d\n"), m_iDVDDomain);
    01695                         MoveVideoWindow(); // AR might have changed
    01696                 }
    01697                 else if(EC_DVD_CURRENT_HMSF_TIME == evCode)
    01698                 {
    01699                         REFERENCE_TIME rtNow = 0, rtDur = 0;
    01700
    01701                         double fps = evParam2 == DVD_TC_FLAG_25fps ? 25.0
    01702                                 : evParam2 == DVD_TC_FLAG_30fps ? 30.0
    01703                                 : evParam2 == DVD_TC_FLAG_DropFrame ? 29.97
    01704                                 : 25.0;
    01705
    01706                         rtNow = HMSF2RT(*((DVD_HMSF_TIMECODE*)&evParam1), fps);
    01707
    01708                         DVD_HMSF_TIMECODE tcDur;
    01709                         ULONG ulFlags;
    01710                         if(SUCCEEDED(pDVDI->GetTotalTitleTime(&tcDur, &ulFlags)))
    01711                         {
    01712                                 rtDur = HMSF2RT(tcDur, fps);
    01713                         }
    01714
    01715                         m_wndSeekBar.Enable(rtDur > 0);
    01716                         m_wndSeekBar.SetRange(0, rtDur);
    01717                         m_wndSeekBar.SetPos(rtNow);
    01718
    01719                         if(m_pSubClock) m_pSubClock->SetTime(rtNow);
    01720                 }
    01721                 else if(EC_DVD_ERROR == evCode)
    01722                 {
    01723                         TRACE(_T("EC_DVD_ERROR %d %d\n"), evParam1, evParam2);
    01724
    01725                         CString err;
    01726
    01727                         switch(evParam1)
    01728                         {
    01729                         case DVD_ERROR_Unexpected: default: err = _T("DVD: Unexpected error"); break;
    01730                         case DVD_ERROR_CopyProtectFail: err = _T("DVD: Copy-Protect Fail"); break;
    01731                         case DVD_ERROR_InvalidDVD1_0Disc: err = _T("DVD: Invalid DVD 1.x Disc"); break;
    01732                         case DVD_ERROR_InvalidDiscRegion: err = _T("DVD: Invalid Disc Region"); break;
    01733                         case DVD_ERROR_LowParentalLevel: err = _T("DVD: Low Parental Level"); break;
    01734                         case DVD_ERROR_MacrovisionFail: err = _T("DVD: Macrovision Fail"); break;
    01735                         case DVD_ERROR_IncompatibleSystemAndDecoderRegions: err = _T("DVD: Incompatible System And Decoder Regions"); break;
    01736                         case DVD_ERROR_IncompatibleDiscAndDecoderRegions: err = _T("DVD: Incompatible Disc And Decoder Regions"); break;
    01737                         }
    01738
    01739                         SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
    01740
    01741                         m_closingmsg = err;
    01742                 }
    01743                 else if(EC_DVD_WARNING == evCode)
    01744                 {
    01745                         TRACE(_T("EC_DVD_WARNING %d %d\n"), evParam1, evParam2);
    01746                 }
    01747                 else if(EC_VIDEO_SIZE_CHANGED == evCode)
    01748                 {
    01749                         TRACE(_T("EC_VIDEO_SIZE_CHANGED %dx%d\n"), CSize(evParam1));
    01750
    01751                         WINDOWPLACEMENT wp;
    01752                         wp.length = sizeof(wp);
    01753                         GetWindowPlacement(&wp);
    01754
    01755                         CSize size(evParam1);
    01756                         m_fAudioOnly = (size.cx <= 0 || size.cy <= 0);
    01757
    01758                         if(AfxGetAppSettings().fRememberZoomLevel
    01759                         && !(m_fFullScreen || wp.showCmd == SW_SHOWMAXIMIZED || wp.showCmd == SW_SHOWMINIMIZED))
    01760                         {
    01761                                 ZoomVideoWindow();
    01762                         }
    01763                         else
    01764                         {
    01765                                 MoveVideoWindow();
    01766                         }
    01767
    01768                         if(m_iMediaLoadState == MLS_LOADED
    01769                         && !m_fAudioOnly && (AfxGetAppSettings().nCLSwitches&CLSW_FULLSCREEN))
    01770                         {
    01771                                 PostMessage(WM_COMMAND, ID_VIEW_FULLSCREEN);
    01772                                 AfxGetAppSettings().nCLSwitches &= ~CLSW_FULLSCREEN;
    01773                         }
    01774                 }
    01775                 else if(EC_LENGTH_CHANGED == evCode)
    01776                 {
    01777                         __int64 rtDur = 0;
    01778                         pMS->GetDuration(&rtDur);
    01779                         m_wndPlaylistBar.SetCurTime(rtDur);
    01780                 }
    01781                 else if(!m_fCustomGraph)
    01782                 {
    01783                         TRACE(_T("%d\n"), evCode);
    01784                 }
    01785                 else if(EC_BG_AUDIO_CHANGED == evCode)
    01786                 {
    01787                         int nAudioChannels = evParam1;
    01788
    01789                         m_wndStatusBar.SetStatusBitmap(nAudioChannels == 1 ? IDB_MONO
    01790                                                                                 : nAudioChannels >= 2 ? IDB_STEREO
    01791                                                                                 : IDB_NOAUDIO);
    01792                 }
    01793                 else if(EC_BG_ERROR == evCode)
    01794                 {
    01795                         SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
    01796                         m_closingmsg = !str.IsEmpty() ? str : _T("Unspecified graph error");
    01797                         m_wndPlaylistBar.SetCurValid(false);
    01798                         break;
    01799                 }
    01800         }
    01801
    01802     return hr;
    01803 }
    01804
    01805 LRESULT CMainFrame::OnRepaintRenderLess(WPARAM wParam, LPARAM lParam)
    01806 {
    01807         MoveVideoWindow();
    01808         return TRUE;
    01809 }
    01810
    01811 LRESULT CMainFrame::OnResumeFromState(WPARAM wParam, LPARAM lParam)
    01812 {
    01813         int iPlaybackMode = (int)wParam;
    01814
    01815         if(iPlaybackMode == PM_FILE)
    01816         {
    01817                 SeekTo(10000i64*int(lParam));
    01818         }
    01819         else if(iPlaybackMode == PM_DVD)
    01820         {
    01821                 CComPtr<IDvdState> pDvdState;
    01822                 pDvdState.Attach((IDvdState*)lParam);
    01823                 if(pDVDC) pDVDC->SetState(pDvdState, DVD_CMD_FLAG_Block, NULL);
    01824         }
    01825         else if(iPlaybackMode == PM_CAPTURE)
    01826         {
    01827                 // not implemented
    01828         }
    01829         else
    01830         {
    01831                 ASSERT(0);
    01832                 return FALSE;
    01833         }
    01834
    01835         return TRUE;
    01836 }
    01837
    01838 BOOL CMainFrame::OnButton(UINT id, UINT nFlags, CPoint point)
    01839 {
    01840         SetFocus();
    01841
    01842         CRect r;
    01843         m_wndView.GetClientRect(r);
    01844         m_wndView.MapWindowPoints(this, &r);
    01845
    01846         if(id != wmcmd::WDOWN && id != wmcmd::WUP && !r.PtInRect(point)) return FALSE;
    01847
    01848         BOOL ret = FALSE;
    01849
    01850         AppSettings& s = AfxGetAppSettings();
    01851         POSITION pos = s.wmcmds.GetHeadPosition();
    01852         while(pos)
    01853         {
    01854                 wmcmd& wc = s.wmcmds.GetNext(pos);
    01855                 if(wc.mouse == id)
    01856                 {
    01857                         SendMessage(WM_COMMAND, wc.cmd);
    01858                         ret = true;
    01859                 }
    01860         }
    01861
    01862         return ret;
    01863 }
    01864
    01865 static bool s_fLDown = false;
    01866
    01867 void CMainFrame::OnLButtonDown(UINT nFlags, CPoint point)
    01868 {
    01869         SetFocus();
    01870
    01871         bool fClicked = false;
    01872
    01873         if(m_iPlaybackMode == PM_DVD)
    01874         {
    01875                 CPoint p = point - m_wndView.GetVideoRect().TopLeft();
    01876
    01877                 if(SUCCEEDED(pDVDC->ActivateAtPosition(p))
    01878                 || m_iDVDDomain == DVD_DOMAIN_VideoManagerMenu
    01879                 || m_iDVDDomain == DVD_DOMAIN_VideoTitleSetMenu)
    01880                         fClicked = true;
    01881         }
    01882
    01883         if(!fClicked)
    01884         {
    01885                 bool fLeftMouseBtnUnassigned = true;
    01886                 AppSettings& s = AfxGetAppSettings();
    01887                 POSITION pos = s.wmcmds.GetHeadPosition();
    01888                 while(pos && fLeftMouseBtnUnassigned)
    01889                         if(s.wmcmds.GetNext(pos).mouse == wmcmd::LDOWN)
    01890                                 fLeftMouseBtnUnassigned = false;
    01891
    01892                 if(!m_fFullScreen && (IsCaptionMenuHidden() || fLeftMouseBtnUnassigned))
    01893                 {
    01894                         PostMessage(WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(point.x, point.y));
    01895                 }
    01896                 else
    01897 {
    01898 s_fLDown = true;
    01899                         if(OnButton(wmcmd::LDOWN, nFlags, point))
    01900                                 return;
    01901 }
    01902         }
    01903
    01904         __super::OnLButtonDown(nFlags, point);
    01905 }
    01906
    01907 void CMainFrame::OnLButtonUp(UINT nFlags, CPoint point)
    01908 {
    01909         if(!OnButton(wmcmd::LUP, nFlags, point))
    01910                 __super::OnLButtonUp(nFlags, point);
    01911 }
    01912
    01913 void CMainFrame::OnLButtonDblClk(UINT nFlags, CPoint point)
    01914 {
    01915 if(s_fLDown)
    01916 {
    01917         SendMessage(WM_LBUTTONDOWN, nFlags, MAKELPARAM(point.x, point.y));
    01918 s_fLDown = false;
    01919 }
    01920         if(!OnButton(wmcmd::LDBLCLK, nFlags, point))
    01921                 __super::OnLButtonDblClk(nFlags, point);
    01922 }
    01923
    01924 void CMainFrame::OnMButtonDown(UINT nFlags, CPoint point)
    01925 {
    01926         SendMessage(WM_CANCELMODE);
    01927         if(!OnButton(wmcmd::MDOWN, nFlags, point))
    01928                 __super::OnMButtonDown(nFlags, point);
    01929 }
    01930
    01931 void CMainFrame::OnMButtonUp(UINT nFlags, CPoint point)
    01932 {
    01933         if(!OnButton(wmcmd::MUP, nFlags, point))
    01934                 __super::OnMButtonUp(nFlags, point);
    01935 }
    01936
    01937 void CMainFrame::OnMButtonDblClk(UINT nFlags, CPoint point)
    01938 {
    01939         SendMessage(WM_MBUTTONDOWN, nFlags, MAKELPARAM(point.x, point.y));
    01940         if(!OnButton(wmcmd::MDBLCLK, nFlags, point))
    01941                 __super::OnMButtonDblClk(nFlags, point);
    01942 }
    01943
    01944 void CMainFrame::OnRButtonDown(UINT nFlags, CPoint point)
    01945 {
    01946         if(!OnButton(wmcmd::RDOWN, nFlags, point))
    01947                 __super::OnRButtonDown(nFlags, point);
    01948 }
    01949
    01950 void CMainFrame::OnRButtonUp(UINT nFlags, CPoint point)
    01951 {
    01952         if(!OnButton(wmcmd::RUP, nFlags, point))
    01953                 __super::OnRButtonUp(nFlags, point);
    01954 }
    01955
    01956 void CMainFrame::OnRButtonDblClk(UINT nFlags, CPoint point)
    01957 {
    01958         SendMessage(WM_RBUTTONDOWN, nFlags, MAKELPARAM(point.x, point.y));
    01959         if(!OnButton(wmcmd::RDBLCLK, nFlags, point))
    01960                 __super::OnRButtonDblClk(nFlags, point);
    01961 }
    01962
    01963 LRESULT CMainFrame::OnXButtonDown(WPARAM wParam, LPARAM lParam)
    01964 {
    01965         SendMessage(WM_CANCELMODE);
    01966         UINT fwButton = GET_XBUTTON_WPARAM(wParam);
    01967         return OnButton(fwButton == XBUTTON1 ? wmcmd::X1DOWN : fwButton == XBUTTON2 ? wmcmd::X2DOWN : wmcmd::NONE,
    01968                 GET_KEYSTATE_WPARAM(wParam), CPoint(lParam));
    01969 }
    01970
    01971 LRESULT CMainFrame::OnXButtonUp(WPARAM wParam, LPARAM lParam)
    01972 {
    01973         UINT fwButton = GET_XBUTTON_WPARAM(wParam);
    01974         return OnButton(fwButton == XBUTTON1 ? wmcmd::X1UP : fwButton == XBUTTON2 ? wmcmd::X2UP : wmcmd::NONE,
    01975                 GET_KEYSTATE_WPARAM(wParam), CPoint(lParam));
    01976 }
    01977
    01978 LRESULT CMainFrame::OnXButtonDblClk(WPARAM wParam, LPARAM lParam)
    01979 {
    01980         SendMessage(WM_XBUTTONDOWN, wParam, lParam);
    01981         UINT fwButton = GET_XBUTTON_WPARAM(wParam);
    01982         return OnButton(fwButton == XBUTTON1 ? wmcmd::X1DBLCLK : fwButton == XBUTTON2 ? wmcmd::X2DBLCLK : wmcmd::NONE,
    01983                 GET_KEYSTATE_WPARAM(wParam), CPoint(lParam));
    01984 }
    01985
    01986 BOOL CMainFrame::OnMouseWheel(UINT nFlags, short zDelta, CPoint point)
    01987 {
    01988         ScreenToClient(&point);
    01989
    01990         BOOL fRet =
    01991                 zDelta > 0 ? OnButton(wmcmd::WUP, nFlags, point) :
    01992                 zDelta < 0 ? OnButton(wmcmd::WDOWN, nFlags, point) :
    01993                 FALSE;
    01994
    01995         return fRet;
    01996 }
    01997
    01998 void CMainFrame::OnMouseMove(UINT nFlags, CPoint point)
    01999 {
    02000         if(m_iPlaybackMode == PM_DVD)
    02001         {
    02002                 CPoint vp = point - m_wndView.GetVideoRect().TopLeft();
    02003                 pDVDC->SelectAtPosition(vp);
    02004         }
    02005
    02006         CSize diff = m_lastMouseMove - point;
    02007
    02008         if(m_fFullScreen && (abs(diff.cx)+abs(diff.cy)) >= 1)
    02009         {
    02010                 int nTimeOut = AfxGetAppSettings().nShowBarsWhenFullScreenTimeOut;
    02011
    02012                 if(nTimeOut < 0)
    02013                 {
    02014                         m_fHideCursor = false;
    02015                         if(AfxGetAppSettings().fShowBarsWhenFullScreen)
    02016                                 ShowControls(AfxGetAppSettings().nCS);
    02017
    02018                         KillTimer(TIMER_FULLSCREENCONTROLBARHIDER);
    02019                         SetTimer(TIMER_FULLSCREENMOUSEHIDER, 2000, NULL);
    02020                 }
    02021                 else if(nTimeOut == 0)
    02022                 {
    02023                         CRect r;
    02024                         GetClientRect(r);
    02025                         r.top = r.bottom;
    02026
    02027                         POSITION pos = m_bars.GetHeadPosition();
    02028                         for(int i = 1; pos; i <<= 1)
    02029                         {
    02030                                 CControlBar* pNext = m_bars.GetNext(pos);
    02031                                 CSize s = pNext->CalcFixedLayout(FALSE, TRUE);
    02032                                 if(AfxGetAppSettings().nCS&i) r.top -= s.cy;
    02033                         }
    02034
    02035                         // HACK: the controls would cover the menu too early hiding some buttons
    02036                         if(m_iPlaybackMode == PM_DVD
    02037                         && (m_iDVDDomain == DVD_DOMAIN_VideoManagerMenu
    02038                         || m_iDVDDomain == DVD_DOMAIN_VideoTitleSetMenu))
    02039                                 r.top = r.bottom - 10;
    02040
    02041                         m_fHideCursor = false;
    02042
    02043                         if(r.PtInRect(point))
    02044                         {
    02045                                 if(AfxGetAppSettings().fShowBarsWhenFullScreen)
    02046                                         ShowControls(AfxGetAppSettings().nCS);
    02047                         }
    02048                         else
    02049                         {
    02050                                 if(AfxGetAppSettings().fShowBarsWhenFullScreen)
    02051                                         ShowControls(CS_NONE, false);
    02052                         }
    02053
    02054                         SetTimer(TIMER_FULLSCREENMOUSEHIDER, 2000, NULL);
    02055                 }
    02056                 else
    02057                 {
    02058                         m_fHideCursor = false;
    02059                         if(AfxGetAppSettings().fShowBarsWhenFullScreen)
    02060                                 ShowControls(AfxGetAppSettings().nCS);
    02061
    02062                         SetTimer(TIMER_FULLSCREENCONTROLBARHIDER, nTimeOut*1000, NULL);
    02063                         SetTimer(TIMER_FULLSCREENMOUSEHIDER, max(nTimeOut*1000, 2000), NULL);
    02064                 }
    02065         }
    02066
    02067         m_lastMouseMove = point;
    02068
    02069         __super::OnMouseMove(nFlags, point);
    02070 }
    02071
    02072 LRESULT CMainFrame::OnNcHitTest(CPoint point)
    02073 {
    02074         LRESULT nHitTest = __super::OnNcHitTest(point);
    02075         return ((IsCaptionMenuHidden()) && nHitTest == HTCLIENT) ? HTCAPTION : nHitTest;
    02076 }
    02077
    02078 void CMainFrame::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
    02079 {
    02080         if(pScrollBar->IsKindOf(RUNTIME_CLASS(CVolumeCtrl)))
    02081         {
    02082                 OnPlayVolume(0);
    02083         }
    02084         else if(pScrollBar->IsKindOf(RUNTIME_CLASS(CPlayerSeekBar)) && m_iMediaLoadState == MLS_LOADED)
    02085         {
    02086                 SeekTo(m_wndSeekBar.GetPos(), !!(::GetKeyState(VK_SHIFT)&0x8000));
    02087         }
    02088
    02089         __super::OnHScroll(nSBCode, nPos, pScrollBar);
    02090 }
    02091
    02092 void CMainFrame::OnInitMenu(CMenu* pMenu)
    02093 {
    02094         __super::OnInitMenu(pMenu);
    02095
    02096         MENUITEMINFO mii;
    02097         mii.cbSize = sizeof(mii);
    02098
    02099         for(UINT i = 0, j = pMenu->GetMenuItemCount(); i < j; i++)
    02100         {
    02101                 CString str;
    02102                 pMenu->GetMenuString(i, str, MF_BYPOSITION);
    02103
    02104                 CMenu* pSubMenu = NULL;
    02105
    02106                 if(str == ResStr(IDS_FAVORITES_POPUP))
    02107                 {
    02108                         SetupFavoritesSubMenu();
    02109                         pSubMenu = &m_favorites;
    02110                 }
    02111
    02112                 if(pSubMenu)
    02113                 {
    02114                         mii.fMask = MIIM_STATE|MIIM_SUBMENU;
    02115                         mii.fType = MF_POPUP;
    02116                         mii.hSubMenu = pSubMenu->m_hMenu;
    02117                         mii.fState = (pSubMenu->GetMenuItemCount() > 0 ? MF_ENABLED : (MF_DISABLED|MF_GRAYED));
    02118                         pMenu->SetMenuItemInfo(i, &mii, TRUE);
    02119                 }
    02120         }
    02121 }
    02122
    02123 void CMainFrame::OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu)
    02124 {
    02125         __super::OnInitMenuPopup(pPopupMenu, nIndex, bSysMenu);
    02126
    02127         static CAtlMap<CString, UINT, CStringElementTraits<CString> > transl;
    02128
    02129         if(transl.IsEmpty())
    02130         {
    02131                 transl[_T("Navigate")] = IDS_NAVIGATE_POPUP;
    02132                 transl[_T("Open CD-ROM")] = IDS_OPENCDROM_POPUP;
    02133                 transl[_T("Filters")] = IDS_FILTERS_POPUP;
    02134                 transl[_T("Audio")] = IDS_AUDIO_POPUP;
    02135                 transl[_T("Subtitles")] = IDS_SUBTITLES_POPUP;
    02136                 transl[_T("Audio Language")] = IDS_AUDIOLANGUAGE_POPUP;
    02137                 transl[_T("Subtitle Language")] = IDS_SUBTITLELANGUAGE_POPUP;
    02138                 transl[_T("Video Angle")] = IDS_VIDEOANGLE_POPUP;
    02139                 transl[_T("Jump To...")] = IDS_JUMPTO_POPUP;
    02140                 transl[_T("Favorites")] = IDS_FAVORITES_POPUP;
    02141                 transl[_T("Shaders")] = IDS_SHADER_POPUP;
    02142                 transl[_T("Video Frame")] = IDS_VIDEOFRAME_POPUP;
    02143                 transl[_T("PanScan")] = IDS_PANSCAN_POPUP;
    02144                 transl[_T("Aspect Ratio")] = IDS_ASPECTRATIO_POPUP;
    02145                 transl[_T("Zoom")] = IDS_ZOOM_POPUP;
    02146         }
    02147
    02148         MENUITEMINFO mii;
    02149         mii.cbSize = sizeof(mii);
    02150
    02151         for(UINT i = 0, j = pPopupMenu->GetMenuItemCount(); i < j; i++)
    02152         {
    02153                 CString str;
    02154                 pPopupMenu->GetMenuString(i, str, MF_BYPOSITION);
    02155
    02156                 CString lookupstr = str;
    02157                 lookupstr.Remove('&');
    02158
    02159                 CMenu* pSubMenu = NULL;
    02160
    02161                 UINT id;
    02162                 if(transl.Lookup(lookupstr, id))
    02163                 {
    02164                         str = ResStr(id);
    02165                         // pPopupMenu->ModifyMenu(i, MF_BYPOSITION|MF_STRING, 0, str);
    02166                         MENUITEMINFO mii;
    02167                         mii.cbSize = sizeof(mii);
    02168                         mii.fMask = MIIM_STRING;
    02169                         mii.dwTypeData = (LPTSTR)(LPCTSTR)str;
    02170                         pPopupMenu->SetMenuItemInfo(i, &mii, TRUE);
    02171                 }
    02172
    02173                 if(str == ResStr(IDS_NAVIGATE_POPUP))
    02174                 {
    02175                         UINT fState = (m_iMediaLoadState == MLS_LOADED
    02176                                 && (1/*m_iPlaybackMode == PM_DVD *//*|| (m_iPlaybackMode == PM_FILE && m_PlayList.GetCount() > 0)*/))
    02177                                 ? MF_ENABLED
    02178                                 : (MF_DISABLED|MF_GRAYED);
    02179
    02180                         pPopupMenu->EnableMenuItem(i, MF_BYPOSITION|fState);
    02181                 }
    02182                 else if(str == ResStr(IDS_VIDEOFRAME_POPUP)
    02183                         || str == ResStr(IDS_PANSCAN_POPUP)
    02184                         || str == ResStr(IDS_ASPECTRATIO_POPUP)
    02185                         || str == ResStr(IDS_ZOOM_POPUP))
    02186                 {
    02187                         UINT fState = (m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly)
    02188                                 ? MF_ENABLED
    02189                                 : (MF_DISABLED|MF_GRAYED);
    02190
    02191                         pPopupMenu->EnableMenuItem(i, MF_BYPOSITION|fState);
    02192                 }
    02193                 else if(str == ResStr(IDS_OPENCDROM_POPUP))
    02194                 {
    02195                         SetupOpenCDSubMenu();
    02196                         pSubMenu = &m_opencds;
    02197                 }
    02198                 else if(str == ResStr(IDS_FILTERS_POPUP))
    02199                 {
    02200                         SetupFiltersSubMenu();
    02201                         pSubMenu = &m_filters;
    02202                 }
    02203                 else if(str == ResStr(IDS_AUDIO_POPUP))
    02204                 {
    02205                         SetupAudioSwitcherSubMenu();
    02206                         pSubMenu = &m_audios;
    02207                 }
    02208                 else if(str == ResStr(IDS_SUBTITLES_POPUP))
    02209                 {
    02210                         SetupSubtitlesSubMenu();
    02211                         pSubMenu = &m_subtitles;
    02212                 }
    02213                 else if(str == ResStr(IDS_AUDIOLANGUAGE_POPUP))
    02214                 {
    02215                         SetupNavAudioSubMenu();
    02216                         pSubMenu = &m_navaudio;
    02217                 }
    02218                 else if(str == ResStr(IDS_SUBTITLELANGUAGE_POPUP))
    02219                 {
    02220                         SetupNavSubtitleSubMenu();
    02221                         pSubMenu = &m_navsubtitle;
    02222                 }
    02223                 else if(str == ResStr(IDS_VIDEOANGLE_POPUP))
    02224                 {
    02225                         SetupNavAngleSubMenu();
    02226                         pSubMenu = &m_navangle;
    02227                 }
    02228                 else if(str == ResStr(IDS_JUMPTO_POPUP))
    02229                 {
    02230                         SetupNavChaptersSubMenu();
    02231                         pSubMenu = &m_navchapters;
    02232                 }
    02233                 else if(str == ResStr(IDS_FAVORITES_POPUP))
    02234                 {
    02235                         SetupFavoritesSubMenu();
    02236                         pSubMenu = &m_favorites;
    02237                 }
    02238                 else if(str == ResStr(IDS_SHADER_POPUP))
    02239                 {
    02240                         SetupShadersSubMenu();
    02241                         pSubMenu = &m_shaders;
    02242                 }
    02243
    02244                 if(pSubMenu)
    02245                 {
    02246                         mii.fMask = MIIM_STATE|MIIM_SUBMENU;
    02247                         mii.fType = MF_POPUP;
    02248                         mii.hSubMenu = pSubMenu->m_hMenu;
    02249                         mii.fState = (pSubMenu->GetMenuItemCount() > 0 ? MF_ENABLED : (MF_DISABLED|MF_GRAYED));
    02250                         pPopupMenu->SetMenuItemInfo(i, &mii, TRUE);
    02251                 }
    02252         }
    02253
    02254         //
    02255
    02256         for(UINT i = 0, j = pPopupMenu->GetMenuItemCount(); i < j; i++)
    02257         {
    02258                 UINT nID = pPopupMenu->GetMenuItemID(i);
    02259                 if(nID == ID_SEPARATOR || nID == -1
    02260                 || nID >= ID_FAVORITES_FILE_START && nID <= ID_FAVORITES_FILE_END
    02261                 || nID >= ID_NAVIGATE_CHAP_SUBITEM_START && nID <= ID_NAVIGATE_CHAP_SUBITEM_END)
    02262                         continue;
    02263
    02264                 CString str;
    02265                 pPopupMenu->GetMenuString(i, str, MF_BYPOSITION);
    02266                 int k = str.Find('\t');
    02267                 if(k > 0) str = str.Left(k);
    02268
    02269                 CString key = CPPageAccelTbl::MakeAccelShortcutLabel(nID);
    02270                 if(!key.IsEmpty()) str += _T("\t") + key;
    02271
    02272                 if(key.IsEmpty() && i < 0) continue;
    02273
    02274                 // BUG(?): this disables menu item update ui calls for some reason...
    02275 //              pPopupMenu->ModifyMenu(i, MF_BYPOSITION|MF_STRING, nID, str);
    02276
    02277                 // this works fine
    02278                 MENUITEMINFO mii;
    02279                 mii.cbSize = sizeof(mii);
    02280                 mii.fMask = MIIM_STRING;
    02281                 mii.dwTypeData = (LPTSTR)(LPCTSTR)str;
    02282                 pPopupMenu->SetMenuItemInfo(i, &mii, TRUE);
    02283
    02284         }
    02285
    02286         //
    02287
    02288         bool fPnSPresets = false;
    02289
    02290         for(UINT i = 0, j = pPopupMenu->GetMenuItemCount(); i < j; i++)
    02291         {
    02292                 UINT nID = pPopupMenu->GetMenuItemID(i);
    02293
    02294                 if(nID >= ID_PANNSCAN_PRESETS_START && nID < ID_PANNSCAN_PRESETS_END)
    02295                 {
    02296                         do
    02297                         {
    02298                                 nID = pPopupMenu->GetMenuItemID(i);
    02299                                 pPopupMenu->DeleteMenu(i, MF_BYPOSITION);
    02300                                 j--;
    02301                         }
    02302                         while(i < j && nID >= ID_PANNSCAN_PRESETS_START && nID < ID_PANNSCAN_PRESETS_END);
    02303
    02304                         nID = pPopupMenu->GetMenuItemID(i);
    02305                 }
    02306
    02307                 if(nID == ID_VIEW_RESET)
    02308                 {
    02309                         fPnSPresets = true;
    02310                 }
    02311         }
    02312
    02313         if(fPnSPresets)
    02314         {
    02315                 AppSettings& s = AfxGetAppSettings();
    02316                 int i = 0, j = s.m_pnspresets.GetCount();
    02317                 for(; i < j; i++)
    02318                 {
    02319                         int k = 0;
    02320                         CString label = s.m_pnspresets[i].Tokenize(_T(","), k);
    02321                         pPopupMenu->InsertMenu(ID_VIEW_RESET, MF_BYCOMMAND, ID_PANNSCAN_PRESETS_START+i, label);
    02322                 }
    02323 //              if(j > 0)
    02324                 {
    02325                         pPopupMenu->InsertMenu(ID_VIEW_RESET, MF_BYCOMMAND, ID_PANNSCAN_PRESETS_START+i, _T("Edit..."));
    02326                         pPopupMenu->InsertMenu(ID_VIEW_RESET, MF_BYCOMMAND|MF_SEPARATOR);
    02327                 }
    02328         }
    02329 }
    02330
    02331 BOOL CMainFrame::OnMenu(CMenu* pMenu)
    02332 {
    02333         if(!pMenu) return FALSE;
    02334
    02335         KillTimer(TIMER_FULLSCREENMOUSEHIDER);
    02336         m_fHideCursor = false;
    02337
    02338         CPoint point;
    02339         GetCursorPos(&point);
    02340
    02341         pMenu->TrackPopupMenu(TPM_RIGHTBUTTON|TPM_NOANIMATION, point.x, point.y, this);
    02342
    02343         return TRUE;
    02344 }
    02345
    02346 void CMainFrame::OnMenuPlayerShort()
    02347 {
    02348         if(IsCaptionMenuHidden())
    02349         {
    02350                 OnMenu(m_popupmain.GetSubMenu(0));
    02351         }
    02352         else
    02353         {
    02354                 OnMenu(m_popup.GetSubMenu(0));
    02355         }
    02356 }
    02357
    02358 void CMainFrame::OnMenuPlayerLong()
    02359 {
    02360         OnMenu(m_popupmain.GetSubMenu(0));
    02361 }
    02362
    02363 void CMainFrame::OnMenuFilters()
    02364 {
    02365         SetupFiltersSubMenu();
    02366         OnMenu(&m_filters);
    02367 }
    02368
    02369 void CMainFrame::OnUpdatePlayerStatus(CCmdUI* pCmdUI)
    02370 {
    02371         if(m_iMediaLoadState == MLS_LOADING)
    02372         {
    02373                 pCmdUI->SetText(_T("Opening..."));
    02374         }
    02375         else if(m_iMediaLoadState == MLS_LOADED)
    02376         {
    02377                 CString msg;
    02378
    02379                 if(!m_playingmsg.IsEmpty())
    02380                 {
    02381                         msg = m_playingmsg;
    02382                 }
    02383                 else if(m_fCapturing)
    02384                 {
    02385                         msg = _T("Capturing...");
    02386
    02387                         if(pAMDF)
    02388                         {
    02389                                 long lDropped = 0;
    02390                                 pAMDF->GetNumDropped(&lDropped);
    02391                                 long lNotDropped = 0;
    02392                                 pAMDF->GetNumNotDropped(&lNotDropped);
    02393
    02394                                 if((lDropped + lNotDropped) > 0)
    02395                                 {
    02396                                         CString str;
    02397                                         str.Format(_T(", Total: %d, Dropped: %d"), lDropped + lNotDropped, lDropped);
    02398                                         msg += str;
    02399                                 }
    02400                         }
    02401
    02402                         CComPtr<IPin> pPin;
    02403                         if(SUCCEEDED(pCGB->FindPin(m_wndCaptureBar.m_capdlg.m_pDst, PINDIR_INPUT, NULL, NULL, FALSE, 0, &pPin)))
    02404                         {
    02405                                 LONGLONG size = 0;
    02406                                 if(CComQIPtr<IStream> pStream = pPin)
    02407                                 {
    02408                                         pStream->Commit(STGC_DEFAULT);
    02409
    02410                                         WIN32_FIND_DATA findFileData;
    02411                                         HANDLE h = FindFirstFile(m_wndCaptureBar.m_capdlg.m_file, &findFileData);
    02412                                         if(h != INVALID_HANDLE_VALUE)
    02413                                         {
    02414                                                 size = ((LONGLONG)findFileData.nFileSizeHigh << 32) | findFileData.nFileSizeLow;
    02415
    02416                                                 CString str;
    02417                                                 if(size < 1024i64*1024)
    02418                                                         str.Format(_T(", Size: %I64dKB"), size/1024);
    02419                                                 else //if(size < 1024i64*1024*1024)
    02420                                                         str.Format(_T(", Size: %I64dMB"), size/1024/1024);
    02421                                                 msg += str;
    02422
    02423                                                 FindClose(h);
    02424                                         }
    02425                                 }
    02426
    02427                                 ULARGE_INTEGER FreeBytesAvailable, TotalNumberOfBytes, TotalNumberOfFreeBytes;
    02428                                 if(GetDiskFreeSpaceEx(
    02429                                         m_wndCaptureBar.m_capdlg.m_file.Left(m_wndCaptureBar.m_capdlg.m_file.ReverseFind('\\')+1),
    02430                                         &FreeBytesAvailable, &TotalNumberOfBytes, &TotalNumberOfFreeBytes))
    02431                                 {
    02432                                         CString str;
    02433                                         if(FreeBytesAvailable.QuadPart < 1024i64*1024)
    02434                                                 str.Format(_T(", Free: %I64dKB"), FreeBytesAvailable.QuadPart/1024);
    02435                                         else //if(FreeBytesAvailable.QuadPart < 1024i64*1024*1024)
    02436                                                 str.Format(_T(", Free: %I64dMB"), FreeBytesAvailable.QuadPart/1024/1024);
    02437                                         msg += str;
    02438                                 }
    02439
    02440                                 if(m_wndCaptureBar.m_capdlg.m_pMux)
    02441                                 {
    02442                                         __int64 pos = 0;
    02443                                         CComQIPtr<IMediaSeeking> pMuxMS = m_wndCaptureBar.m_capdlg.m_pMux;
    02444                                         if(pMuxMS && SUCCEEDED(pMuxMS->GetCurrentPosition(&pos)) && pos > 0)
    02445                                         {
    02446                                                 double bytepersec = 10000000.0 * size / pos;
    02447                                                 if(bytepersec > 0)
    02448                                                         m_rtDurationOverride = __int64(10000000.0 * (FreeBytesAvailable.QuadPart+size) / bytepersec);
    02449                                         }
    02450                                 }
    02451
    02452                                 if(m_wndCaptureBar.m_capdlg.m_pVidBuffer
    02453                                 || m_wndCaptureBar.m_capdlg.m_pAudBuffer)
    02454                                 {
    02455                                         int nFreeVidBuffers = 0, nFreeAudBuffers = 0;
    02456                                         if(CComQIPtr<IBufferFilter> pVB = m_wndCaptureBar.m_capdlg.m_pVidBuffer)
    02457                                                 nFreeVidBuffers = pVB->GetFreeBuffers();
    02458                                         if(CComQIPtr<IBufferFilter> pAB = m_wndCaptureBar.m_capdlg.m_pAudBuffer)
    02459                                                 nFreeAudBuffers = pAB->GetFreeBuffers();
    02460
    02461                                         CString str;
    02462                                         str.Format(_T(", Free V/A Buffers: %03d/%03d"), nFreeVidBuffers, nFreeAudBuffers);
    02463                                         msg += str;
    02464                                 }
    02465                         }
    02466                 }
    02467                 else if(m_fBuffering)
    02468                 {
    02469                         BeginEnumFilters(pGB, pEF, pBF)
    02470                         {
    02471                                 if(CComQIPtr<IAMNetworkStatus, &IID_IAMNetworkStatus> pAMNS = pBF)
    02472                                 {
    02473                                         long BufferingProgress = 0;
    02474                                         if(SUCCEEDED(pAMNS->get_BufferingProgress(&BufferingProgress)) && BufferingProgress > 0)
    02475                                         {
    02476                                                 msg.Format(_T("Buffering... (%d%%)"), BufferingProgress);
    02477
    02478                                                 __int64 start = 0, stop = 0;
    02479                                                 m_wndSeekBar.GetRange(start, stop);
    02480                                                 m_fLiveWM = (stop == start);
    02481                                         }
    02482                                         break;
    02483                                 }
    02484                         }
    02485                         EndEnumFilters
    02486                 }
    02487                 else if(pAMOP)
    02488                 {
    02489                         __int64 t = 0, c = 0;
    02490                         if(SUCCEEDED(pAMOP->QueryProgress(&t, &c)) && t > 0 && c < t)
    02491                                 msg.Format(_T("Buffering... (%d%%)"), c*100/t);
    02492
    02493                         if(m_fUpdateInfoBar)
    02494                                 OpenSetupInfoBar();
    02495                 }
    02496
    02497                 OAFilterState fs = GetMediaState();
    02498                 pCmdUI->SetText(
    02499                         !msg.IsEmpty() ? msg :
    02500                         fs == State_Stopped ? _T("Stopped") :
    02501                         (fs == State_Paused || m_fFrameSteppingActive) ? _T("Paused") :
    02502                         fs == State_Running ? _T("Playing") :
    02503                         _T(""));
    02504         }
    02505         else if(m_iMediaLoadState == MLS_CLOSING)
    02506         {
    02507                 pCmdUI->SetText(_T("Closing..."));
    02508         }
    02509         else
    02510         {
    02511                 pCmdUI->SetText(m_closingmsg);
    02512         }
    02513 }
    02514
    02515 void CMainFrame::OnFilePostOpenmedia()
    02516 {
    02517         OpenSetupInfoBar();
    02518
    02519         OpenSetupStatsBar();
    02520
    02521         OpenSetupStatusBar();
    02522
    02523         // OpenSetupToolBar();
    02524
    02525         OpenSetupCaptureBar();
    02526
    02527         __int64 rtDur = 0;
    02528         pMS->GetDuration(&rtDur);
    02529         m_wndPlaylistBar.SetCurTime(rtDur);
    02530
    02531         if(m_iPlaybackMode == PM_CAPTURE)
    02532         {
    02533                 ShowControlBar(&m_wndSubresyncBar, FALSE, TRUE);
    02534 //              ShowControlBar(&m_wndPlaylistBar, FALSE, TRUE);
    02535 //              ShowControlBar(&m_wndCaptureBar, TRUE, TRUE);
    02536         }
    02537
    02538         m_iMediaLoadState = MLS_LOADED;
    02539
    02540         // IMPORTANT: must not call any windowing msgs before
    02541         // this point, it will deadlock when OpenMediaPrivate is
    02542         // still running and the renderer window was created on
    02543         // the same worker-thread
    02544
    02545         {
    02546                 WINDOWPLACEMENT wp;
    02547                 wp.length = sizeof(wp);
    02548                 GetWindowPlacement(&wp);
    02549
    02550                 // restore magnification
    02551                 if(IsWindowVisible() && AfxGetAppSettings().fRememberZoomLevel
    02552                 && !(m_fFullScreen || wp.showCmd == SW_SHOWMAXIMIZED || wp.showCmd == SW_SHOWMINIMIZED))
    02553                 {
    02554                         ZoomVideoWindow();
    02555                 }
    02556         }
    02557
    02558         if(!m_fAudioOnly && (AfxGetAppSettings().nCLSwitches&CLSW_FULLSCREEN))
    02559         {
    02560                 SendMessage(WM_COMMAND, ID_VIEW_FULLSCREEN);
    02561                 AfxGetAppSettings().nCLSwitches &= ~CLSW_FULLSCREEN;
    02562         }
    02563
    02564         SendNowPlayingToMSN();
    02565 }
    02566
    02567 void CMainFrame::OnUpdateFilePostOpenmedia(CCmdUI* pCmdUI)
    02568 {
    02569         pCmdUI->Enable(m_iMediaLoadState == MLS_LOADING);
    02570 }
    02571
    02572 void CMainFrame::OnFilePostClosemedia()
    02573 {
    02574         m_wndView.SetVideoRect();
    02575         m_wndSeekBar.Enable(false);
    02576         m_wndSeekBar.SetPos(0);
    02577         m_wndInfoBar.RemoveAllLines();
    02578         m_wndStatsBar.RemoveAllLines();
    02579         m_wndStatusBar.Clear();
    02580         m_wndStatusBar.ShowTimer(false);
    02581
    02582         if(IsWindow(m_wndSubresyncBar.m_hWnd))
    02583         {
    02584                 ShowControlBar(&m_wndSubresyncBar, FALSE, TRUE);
    02585                 SetSubtitle(NULL);
    02586         }
    02587
    02588         if(IsWindow(m_wndCaptureBar.m_hWnd))
    02589         {
    02590                 ShowControlBar(&m_wndCaptureBar, FALSE, TRUE);
    02591                 m_wndCaptureBar.m_capdlg.SetupVideoControls(_T(""), NULL, NULL, NULL);
    02592                 m_wndCaptureBar.m_capdlg.SetupAudioControls(_T(""), NULL, CInterfaceArray<IAMAudioInputMixer>());
    02593         }
    02594
    02595         RecalcLayout();
    02596
    02597         SetWindowText(ResStr(IDR_MAINFRAME));
    02598
    02599         SetAlwaysOnTop(AfxGetAppSettings().iOnTop);
    02600
    02601         // this will prevent any further UI updates on the dynamically added menu items
    02602         SetupFiltersSubMenu();
    02603         SetupAudioSwitcherSubMenu();
    02604         SetupSubtitlesSubMenu();
    02605         SetupNavAudioSubMenu();
    02606         SetupNavSubtitleSubMenu();
    02607         SetupNavAngleSubMenu();
    02608         SetupNavChaptersSubMenu();
    02609         SetupFavoritesSubMenu();
    02610
    02611         SendNowPlayingToMSN();
    02612 }
    02613
    02614 void CMainFrame::OnUpdateFilePostClosemedia(CCmdUI* pCmdUI)
    02615 {
    02616         pCmdUI->Enable(!!m_hWnd && m_iMediaLoadState == MLS_CLOSING);
    02617 }
    02618
    02619 void CMainFrame::OnBossKey()
    02620 {
    02621         SendMessage(WM_COMMAND, ID_PLAY_PAUSE);
    02622         if(m_fFullScreen) SendMessage(WM_COMMAND, ID_VIEW_FULLSCREEN);
    02623         SendMessage(WM_SYSCOMMAND, SC_MINIMIZE, -1);
    02624 }
    02625
    02626 void CMainFrame::OnStreamAudio(UINT nID)
    02627 {
    02628         nID -= ID_STREAM_AUDIO_NEXT;
    02629
    02630         if(m_iMediaLoadState != MLS_LOADED) return;
    02631
    02632         CComQIPtr<IAMStreamSelect> pSS = FindFilter(__uuidof(CAudioSwitcherFilter), pGB);
    02633         if(!pSS) pSS = FindFilter(L"{D3CD7858-971A-4838-ACEC-40CA5D529DC8}", pGB); // morgan's switcher
    02634
    02635         DWORD cStreams = 0;
    02636         if(pSS && SUCCEEDED(pSS->Count(&cStreams)) && cStreams > 1)
    02637         {
    02638                 for(int i = 0; i < (int)cStreams; i++)
    02639                 {
    02640                         AM_MEDIA_TYPE* pmt = NULL;
    02641                         DWORD dwFlags = 0;
    02642                         LCID lcid = 0;
    02643                         DWORD dwGroup = 0;
    02644                         WCHAR* pszName = NULL;
    02645                         if(FAILED(pSS->Info(i, &pmt, &dwFlags, &lcid, &dwGroup, &pszName, NULL, NULL)))
    02646                                 return;
    02647                         if(pmt) DeleteMediaType(pmt);
    02648                         if(pszName) CoTaskMemFree(pszName);
    02649
    02650                         if(dwFlags&(AMSTREAMSELECTINFO_ENABLED|AMSTREAMSELECTINFO_EXCLUSIVE))
    02651                         {
    02652                                 pSS->Enable((i+(nID==0?1:cStreams-1))%cStreams, AMSTREAMSELECTENABLE_ENABLE);
    02653                                 break;
    02654                         }
    02655                 }
    02656         }
    02657         else if(m_iPlaybackMode == PM_FILE) SendMessage(WM_COMMAND, ID_OGM_AUDIO_NEXT+nID);
    02658         else if(m_iPlaybackMode == PM_DVD) SendMessage(WM_COMMAND, ID_DVD_AUDIO_NEXT+nID);
    02659 }
    02660
    02661 void CMainFrame::OnStreamSub(UINT nID)
    02662 {
    02663         nID -= ID_STREAM_SUB_NEXT;
    02664
    02665         if(m_iMediaLoadState != MLS_LOADED) return;
    02666
    02667         int cnt = 0;
    02668         POSITION pos = m_pSubStreams.GetHeadPosition();
    02669         while(pos) cnt += m_pSubStreams.GetNext(pos)->GetStreamCount();
    02670
    02671         if(cnt > 1)
    02672         {
    02673                 int i = ((m_iSubtitleSel&0x7fffffff)+(nID==0?1:cnt-1))%cnt;
    02674                 m_iSubtitleSel = i | (m_iSubtitleSel&0x80000000);
    02675                 UpdateSubtitle();
    02676                 SetFocus();
    02677         }
    02678         else if(m_iPlaybackMode == PM_FILE) SendMessage(WM_COMMAND, ID_OGM_SUB_NEXT+nID);
    02679         else if(m_iPlaybackMode == PM_DVD) SendMessage(WM_COMMAND, ID_DVD_SUB_NEXT+nID);
    02680 }
    02681
    02682 void CMainFrame::OnStreamSubOnOff()
    02683 {
    02684         if(m_iMediaLoadState != MLS_LOADED) return;
    02685
    02686         int cnt = 0;
    02687         POSITION pos = m_pSubStreams.GetHeadPosition();
    02688         while(pos) cnt += m_pSubStreams.GetNext(pos)->GetStreamCount();
    02689
    02690         if(cnt > 0)
    02691         {
    02692                 m_iSubtitleSel ^= 0x80000000;
    02693                 UpdateSubtitle();
    02694                 SetFocus();
    02695         }
    02696         else if(m_iPlaybackMode == PM_DVD) SendMessage(WM_COMMAND, ID_DVD_SUB_ONOFF);
    02697 }
    02698
    02699 void CMainFrame::OnOgmAudio(UINT nID)
    02700 {
    02701         nID -= ID_OGM_AUDIO_NEXT;
    02702
    02703         if(m_iMediaLoadState != MLS_LOADED) return;
    02704
    02705         CComQIPtr<IAMStreamSelect> pSS = FindFilter(CLSID_OggSplitter, pGB);
    02706         if(!pSS) pSS = FindFilter(L"{55DA30FC-F16B-49fc-BAA5-AE59FC65F82D}", pGB);
    02707         if(!pSS) return;
    02708
    02709     CArray<int> snds;
    02710         int iSel = -1;
    02711
    02712         DWORD cStreams = 0;
    02713         if(SUCCEEDED(pSS->Count(&cStreams)) && cStreams > 1)
    02714         {
    02715                 for(int i = 0; i < (int)cStreams; i++)
    02716                 {
    02717                         AM_MEDIA_TYPE* pmt = NULL;
    02718                         DWORD dwFlags = 0;
    02719                         LCID lcid = 0;
    02720                         DWORD dwGroup = 0;
    02721                         WCHAR* pszName = NULL;
    02722                         if(FAILED(pSS->Info(i, &pmt, &dwFlags, &lcid, &dwGroup, &pszName, NULL, NULL)))
    02723                                 return;
    02724
    02725                         if(dwGroup == 1)
    02726                         {
    02727                                 if(dwFlags&(AMSTREAMSELECTINFO_ENABLED|AMSTREAMSELECTINFO_EXCLUSIVE))
    02728                                         iSel = snds.GetCount();
    02729                                 snds.Add(i);
    02730                         }
    02731
    02732                         if(pmt) DeleteMediaType(pmt);
    02733                         if(pszName) CoTaskMemFree(pszName);
    02734
    02735                 }
    02736
    02737                 int cnt = snds.GetCount();
    02738                 if(cnt > 1 && iSel >= 0)
    02739                         pSS->Enable(snds[(iSel+(nID==0?1:cnt-1))%cnt], AMSTREAMSELECTENABLE_ENABLE);
    02740         }
    02741 }
    02742
    02743 void CMainFrame::OnOgmSub(UINT nID)
    02744 {
    02745         nID -= ID_OGM_SUB_NEXT;
    02746
    02747         if(m_iMediaLoadState != MLS_LOADED) return;
    02748
    02749         CComQIPtr<IAMStreamSelect> pSS = FindFilter(CLSID_OggSplitter, pGB);
    02750         if(!pSS) pSS = FindFilter(L"{55DA30FC-F16B-49fc-BAA5-AE59FC65F82D}", pGB);
    02751         if(!pSS) return;
    02752
    02753     CArray<int> subs;
    02754         int iSel = -1;
    02755
    02756         DWORD cStreams = 0;
    02757         if(SUCCEEDED(pSS->Count(&cStreams)) && cStreams > 1)
    02758         {
    02759                 for(int i = 0; i < (int)cStreams; i++)
    02760                 {
    02761                         AM_MEDIA_TYPE* pmt = NULL;
    02762                         DWORD dwFlags = 0;
    02763                         LCID lcid = 0;
    02764                         DWORD dwGroup = 0;
    02765                         WCHAR* pszName = NULL;
    02766                         if(FAILED(pSS->Info(i, &pmt, &dwFlags, &lcid, &dwGroup, &pszName, NULL, NULL)))
    02767                                 return;
    02768
    02769                         if(dwGroup == 2)
    02770                         {
    02771                                 if(dwFlags&(AMSTREAMSELECTINFO_ENABLED|AMSTREAMSELECTINFO_EXCLUSIVE))
    02772                                         iSel = subs.GetCount();
    02773                                 subs.Add(i);
    02774                         }
    02775
    02776                         if(pmt) DeleteMediaType(pmt);
    02777                         if(pszName) CoTaskMemFree(pszName);
    02778
    02779                 }
    02780
    02781                 int cnt = subs.GetCount();
    02782                 if(cnt > 1 && iSel >= 0)
    02783                         pSS->Enable(subs[(iSel+(nID==0?1:cnt-1))%cnt], AMSTREAMSELECTENABLE_ENABLE);
    02784         }
    02785 }
    02786
    02787 void CMainFrame::OnDvdAngle(UINT nID)
    02788 {
    02789         nID -= ID_DVD_ANGLE_NEXT;
    02790
    02791         if(m_iMediaLoadState != MLS_LOADED) return;
    02792
    02793         if(pDVDI && pDVDC)
    02794         {
    02795                 ULONG ulAnglesAvailable, ulCurrentAngle;
    02796                 if(SUCCEEDED(pDVDI->GetCurrentAngle(&ulAnglesAvailable, &ulCurrentAngle))
    02797                 && ulAnglesAvailable > 1)
    02798                 {
    02799                         pDVDC->SelectAngle(
    02800                                 (ulCurrentAngle+(nID==0?1:ulAnglesAvailable-1))%ulAnglesAvailable,
    02801                                 DVD_CMD_FLAG_Block, NULL);
    02802                 }
    02803         }
    02804 }
    02805
    02806 void CMainFrame::OnDvdAudio(UINT nID)
    02807 {
    02808         nID -= ID_DVD_AUDIO_NEXT;
    02809
    02810         if(m_iMediaLoadState != MLS_LOADED) return;
    02811
    02812         if(pDVDI && pDVDC)
    02813         {
    02814                 ULONG nStreamsAvailable, nCurrentStream;
    02815                 if(SUCCEEDED(pDVDI->GetCurrentAudio(&nStreamsAvailable, &nCurrentStream))
    02816                 && nStreamsAvailable > 1)
    02817                 {
    02818                         pDVDC->SelectAudioStream(
    02819                                 (nCurrentStream+(nID==0?1:nStreamsAvailable-1))%nStreamsAvailable,
    02820                                 DVD_CMD_FLAG_Block, NULL);
    02821                 }
    02822         }
    02823 }
    02824
    02825 void CMainFrame::OnDvdSub(UINT nID)
    02826 {
    02827         nID -= ID_DVD_SUB_NEXT;
    02828
    02829         if(m_iMediaLoadState != MLS_LOADED) return;
    02830
    02831         if(pDVDI && pDVDC)
    02832         {
    02833                 ULONG ulStreamsAvailable, ulCurrentStream;
    02834                 BOOL bIsDisabled;
    02835                 if(SUCCEEDED(pDVDI->GetCurrentSubpicture(&ulStreamsAvailable, &ulCurrentStream, &bIsDisabled))
    02836                 && ulStreamsAvailable > 1)
    02837                 {
    02838                         pDVDC->SelectSubpictureStream(
    02839                                 (ulCurrentStream+(nID==0?1:ulStreamsAvailable-1))%ulStreamsAvailable,
    02840                                 DVD_CMD_FLAG_Block, NULL);
    02841                 }
    02842         }
    02843 }
    02844
    02845 void CMainFrame::OnDvdSubOnOff()
    02846 {
    02847         if(m_iMediaLoadState != MLS_LOADED) return;
    02848
    02849         if(pDVDI && pDVDC)
    02850         {
    02851                 ULONG ulStreamsAvailable, ulCurrentStream;
    02852                 BOOL bIsDisabled;
    02853                 if(SUCCEEDED(pDVDI->GetCurrentSubpicture(&ulStreamsAvailable, &ulCurrentStream, &bIsDisabled)))
    02854                 {
    02855                         pDVDC->SetSubpictureState(bIsDisabled, DVD_CMD_FLAG_Block, NULL);
    02856                 }
    02857         }
    02858 }
    02859
    02860 //
    02861 // menu item handlers
    02862 //
    02863
    02864 // file
    02865
    02866 void CMainFrame::OnFileOpenmedia()
    02867 {
    02868         if(m_iMediaLoadState == MLS_LOADING || !IsWindow(m_wndPlaylistBar)) return;
    02869
    02870         COpenDlg dlg;
    02871         if(dlg.DoModal() != IDOK || dlg.m_fns.GetCount() == 0) return;
    02872
    02873         SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
    02874
    02875         ShowWindow(SW_SHOW);
    02876         SetForegroundWindow();
    02877
    02878         m_wndPlaylistBar.Open(dlg.m_fns, dlg.m_fMultipleFiles);
    02879
    02880         if(m_wndPlaylistBar.GetCount() == 1 && m_wndPlaylistBar.IsWindowVisible() && !m_wndPlaylistBar.IsFloating())
    02881         {
    02882                 ShowControlBar(&m_wndPlaylistBar, FALSE, TRUE);
    02883         }
    02884
    02885         OpenCurPlaylistItem();
    02886 }
    02887
    02888 void CMainFrame::OnUpdateFileOpen(CCmdUI* pCmdUI)
    02889 {
    02890         pCmdUI->Enable(m_iMediaLoadState != MLS_LOADING);
    02891 }
    02892
    02893 BOOL CMainFrame::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCDS)
    02894 {
    02895         if(m_iMediaLoadState == MLS_LOADING || !IsWindow(m_wndPlaylistBar))
    02896                 return FALSE;
    02897
    02898         if(pCDS->dwData != 0x6ABE51 || pCDS->cbData < sizeof(DWORD))
    02899                 return FALSE;
    02900
    02901         DWORD len = *((DWORD*)pCDS->lpData);
    02902         TCHAR* pBuff = (TCHAR*)((DWORD*)pCDS->lpData + 1);
    02903         TCHAR* pBuffEnd = (TCHAR*)((BYTE*)pBuff + pCDS->cbData - sizeof(DWORD));
    02904
    02905         CList<CString> cmdln;
    02906
    02907         while(len-- > 0)
    02908         {
    02909                 CString str;
    02910                 while(pBuff < pBuffEnd && *pBuff) str += *pBuff++;
    02911                 pBuff++;
    02912                 cmdln.AddTail(str);
    02913         }
    02914
    02915         AppSettings& s = AfxGetAppSettings();
    02916
    02917         s.ParseCommandLine(cmdln);
    02918
    02919         POSITION pos = s.slFilters.GetHeadPosition();
    02920         while(pos)
    02921         {
    02922                 CString fullpath = MakeFullPath(s.slFilters.GetNext(pos));
    02923
    02924                 CPath tmp(fullpath);
    02925                 tmp.RemoveFileSpec();
    02926                 tmp.AddBackslash();
    02927                 CString path = tmp;
    02928
    02929                 WIN32_FIND_DATA fd = {0};
    02930                 HANDLE hFind = FindFirstFile(fullpath, &fd);
    02931                 if(hFind != INVALID_HANDLE_VALUE)
    02932                 {
    02933                         do
    02934                         {
    02935                                 if(fd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) continue;
    02936
    02937                                 CFilterMapper2 fm2(false);
    02938                                 fm2.Register(path + fd.cFileName);
    02939                                 while(!fm2.m_filters.IsEmpty())
    02940                                 {
    02941                                         if(Filter* f = fm2.m_filters.RemoveTail())
    02942                                         {
    02943                                                 f->fTemporary = true;
    02944
    02945                                                 bool fFound = false;
    02946
    02947                                                 POSITION pos2 = s.filters.GetHeadPosition();
    02948                                                 while(pos2)
    02949                                                 {
    02950                                                         Filter* f2 = s.filters.GetNext(pos2);
    02951                                                         if(f2->type == Filter::EXTERNAL && !f2->path.CompareNoCase(f->path))
    02952                                                         {
    02953                                                                 fFound = true;
    02954                                                                 break;
    02955                                                         }
    02956                                                 }
    02957
    02958                                                 if(!fFound)
    02959                                                 {
    02960                                                         CAutoPtr<Filter> p(f);
    02961                                                         s.filters.AddHead(p);
    02962                                                 }
    02963                                         }
    02964                                 }
    02965                         }
    02966                         while(FindNextFile(hFind, &fd));
    02967
    02968                         FindClose(hFind);
    02969                 }
    02970         }
    02971
    02972         bool fSetForegroundWindow = false;
    02973
    02974         if((s.nCLSwitches&CLSW_DVD) && !s.slFiles.IsEmpty())
    02975         {
    02976                 SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
    02977                 fSetForegroundWindow = true;
    02978
    02979                 CAutoPtr<OpenDVDData> p(new OpenDVDData());
    02980                 if(p) {p->path = s.slFiles.GetHead(); p->subs.AddTail(&s.slSubs);}
    02981                 OpenMedia(p);
    02982         }
    02983         else if(s.nCLSwitches&CLSW_CD)
    02984         {
    02985                 SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
    02986                 fSetForegroundWindow = true;
    02987
    02988                 CList<CString> sl;
    02989
    02990                 if(!s.slFiles.IsEmpty())
    02991                 {
    02992                         GetCDROMType(s.slFiles.GetHead()[0], sl);
    02993                 }
    02994                 else
    02995                 {
    02996                         CString dir;
    02997                         dir.ReleaseBufferSetLength(GetCurrentDirectory(MAX_PATH, dir.GetBuffer(MAX_PATH)));
    02998
    02999                         GetCDROMType(dir[0], sl);
    03000
    03001                         for(TCHAR drive = 'C'; sl.IsEmpty() && drive <= 'Z'; drive++)
    03002                         {
    03003                                 GetCDROMType(drive, sl);
    03004                         }
    03005                 }
    03006
    03007                 m_wndPlaylistBar.Open(sl, true);
    03008                 OpenCurPlaylistItem();
    03009         }
    03010         else if(!s.slFiles.IsEmpty())
    03011         {
    03012                 bool fMulti = s.slFiles.GetCount() > 1;
    03013
    03014                 CList<CString> sl;
    03015                 sl.AddTail((CList<CString>*)&s.slFiles);
    03016                 if(!fMulti) sl.AddTail((CList<CString>*)&s.slDubs);
    03017
    03018                 if((s.nCLSwitches&CLSW_ADD) && m_wndPlaylistBar.GetCount() > 0)
    03019                 {
    03020                         m_wndPlaylistBar.Append(sl, fMulti, &s.slSubs);
    03021
    03022                         if(s.nCLSwitches&(CLSW_OPEN|CLSW_PLAY))
    03023                         {
    03024                                 m_wndPlaylistBar.SetLast();
    03025                                 OpenCurPlaylistItem();
    03026                         }
    03027                 }
    03028                 else
    03029                 {
    03030                         SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
    03031                         fSetForegroundWindow = true;
    03032
    03033                         m_wndPlaylistBar.Open(sl, fMulti, &s.slSubs);
    03034                         OpenCurPlaylistItem((s.nCLSwitches&CLSW_STARTVALID) ? s.rtStart : 0);
    03035
    03036                         s.nCLSwitches &= ~CLSW_STARTVALID;
    03037                         s.rtStart = 0;
    03038                 }
    03039         }
    03040         else
    03041         {
    03042                 s.nCLSwitches = CLSW_NONE;
    03043         }
    03044
    03045         if(fSetForegroundWindow && !(s.nCLSwitches&CLSW_NOFOCUS))
    03046                 SetForegroundWindow();
    03047
    03048         s.nCLSwitches &= ~CLSW_NOFOCUS;
    03049
    03050         return TRUE;
    03051 }
    03052
    03053 void CMainFrame::OnFileOpendvd()
    03054 {
    03055         if(m_iMediaLoadState == MLS_LOADING) return;
    03056
    03057         SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
    03058         SetForegroundWindow();
    03059
    03060         ShowWindow(SW_SHOW);
    03061
    03062         CAutoPtr<OpenDVDData> p(new OpenDVDData());
    03063         if(p)
    03064         {
    03065         AppSettings& s = AfxGetAppSettings();
    03066                 if(s.fUseDVDPath && !s.sDVDPath.IsEmpty())
    03067                 {
    03068                         p->path = s.sDVDPath;
    03069                         p->path.Replace('/', '\\');
    03070                         if(p->path[p->path.GetLength()-1] != '\\') p->path += '\\';
    03071                 }
    03072         }
    03073         OpenMedia(p);
    03074 }
    03075
    03076 void CMainFrame::OnFileOpendevice()
    03077 {
    03078         if(m_iMediaLoadState == MLS_LOADING) return;
    03079
    03080         COpenCapDeviceDlg capdlg;
    03081         if(capdlg.DoModal() != IDOK)
    03082                 return;
    03083
    03084         SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
    03085         SetForegroundWindow();
    03086
    03087         ShowWindow(SW_SHOW);
    03088
    03089         m_wndPlaylistBar.Empty();
    03090
    03091         CAutoPtr<OpenDeviceData> p(new OpenDeviceData());
    03092         if(p) {p->DisplayName[0] = capdlg.m_vidstr; p->DisplayName[1] = capdlg.m_audstr;}
    03093         OpenMedia(p);
    03094 }
    03095
    03096 void CMainFrame::OnFileOpenCD(UINT nID)
    03097 {
    03098         nID -= ID_FILE_OPEN_CD_START;
    03099
    03100         nID++;
    03101         for(TCHAR drive = 'C'; drive <= 'Z'; drive++)
    03102         {
    03103                 CList<CString> sl;
    03104
    03105                 switch(GetCDROMType(drive, sl))
    03106                 {
    03107                 case CDROM_Audio:
    03108                 case CDROM_VideoCD:
    03109                 case CDROM_DVDVideo:
    03110                         nID--;
    03111                         break;
    03112                 default:
    03113                         break;
    03114                 }
    03115
    03116                 if(nID == 0)
    03117                 {
    03118                         SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
    03119                         SetForegroundWindow();
    03120
    03121                         ShowWindow(SW_SHOW);
    03122
    03123                         m_wndPlaylistBar.Open(sl, true);
    03124                         OpenCurPlaylistItem();
    03125
    03126                         break;
    03127                 }
    03128         }
    03129 }
    03130
    03131 void CMainFrame::OnDropFiles(HDROP hDropInfo)
    03132 {
    03133         SetForegroundWindow();
    03134
    03135         if(m_wndPlaylistBar.IsWindowVisible())
    03136         {
    03137                 m_wndPlaylistBar.OnDropFiles(hDropInfo);
    03138                 return;
    03139         }
    03140
    03141         CList<CString> sl;
    03142
    03143         UINT nFiles = ::DragQueryFile(hDropInfo, (UINT)-1, NULL, 0);
    03144         for(UINT iFile = 0; iFile < nFiles; iFile++)
    03145         {
    03146                 CString fn;
    03147                 fn.ReleaseBuffer(::DragQueryFile(hDropInfo, iFile, fn.GetBuffer(MAX_PATH), MAX_PATH));
    03148                 sl.AddTail(fn);
    03149         }
    03150         ::DragFinish(hDropInfo);
    03151
    03152         if(!sl.IsEmpty())
    03153         {
    03154                 m_wndPlaylistBar.Open(sl, true);
    03155                 OpenCurPlaylistItem();
    03156         }
    03157 }
    03158
    03159 void CMainFrame::OnFileSaveas()
    03160 {
    03161         CString ext, in = m_wndPlaylistBar.GetCur(), out = in;
    03162
    03163         if(out.Find(_T("://")) < 0)
    03164         {
    03165                 ext = CString(CPath(out).GetExtension()).MakeLower();
    03166                 if(ext == _T(".cda")) out = out.Left(out.GetLength()-4) + _T(".wav");
    03167                 else if(ext == _T(".ifo")) out = out.Left(out.GetLength()-4) + _T(".vob");
    03168         }
    03169         else
    03170         {
    03171                 out.Empty();
    03172         }
    03173
    03174         CFileDialog fd(FALSE, 0, out,
    03175                 OFN_EXPLORER|OFN_ENABLESIZING|OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_PATHMUSTEXIST,
    03176                 _T("All files (*.*)|*.*||"), this, 0);
    03177         if(fd.DoModal() != IDOK || !in.CompareNoCase(fd.GetPathName())) return;
    03178
    03179         CPath p(fd.GetPathName());
    03180         if(!ext.IsEmpty()) p.AddExtension(ext);
    03181
    03182         OAFilterState fs = State_Stopped;
    03183         pMC->GetState(0, &fs);
    03184         if(fs == State_Running) pMC->Pause();
    03185
    03186         CSaveDlg dlg(in, p);
    03187         dlg.DoModal();
    03188
    03189         if(fs == State_Running) pMC->Run();
    03190 }
    03191
    03192 void CMainFrame::OnUpdateFileSaveas(CCmdUI* pCmdUI)
    03193 {
    03194         if(m_iMediaLoadState != MLS_LOADED || m_iPlaybackMode != PM_FILE)
    03195         {
    03196                 pCmdUI->Enable(FALSE);
    03197                 return;
    03198         }
    03199
    03200     CString fn = m_wndPlaylistBar.GetCur();
    03201         CString ext = fn.Mid(fn.ReverseFind('.')+1).MakeLower();
    03202
    03203         if(fn.Find(_T("://")) >= 0)
    03204         {
    03205                 pCmdUI->Enable(FALSE);
    03206                 return;
    03207         }
    03208
    03209         if((GetVersion()&0x80000000) && (ext == _T("cda") || ext == _T("ifo")))
    03210         {
    03211                 pCmdUI->Enable(FALSE);
    03212                 return;
    03213         }
    03214
    03215         pCmdUI->Enable(TRUE);
    03216 }
    03217
    03218 bool CMainFrame::GetDIB(BYTE** ppData, long& size, bool fSilent)
    03219 {
    03220         if(!ppData) return false;
    03221
    03222         *ppData = NULL;
    03223         size = 0;
    03224
    03225         bool fNeedsToPause = !m_pCAP;
    03226         if(fNeedsToPause) fNeedsToPause = !IsVMR7InGraph(pGB);
    03227         if(fNeedsToPause) fNeedsToPause = !IsVMR9InGraph(pGB);
    03228
    03229         OAFilterState fs = GetMediaState();
    03230
    03231         if(!(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly && (fs == State_Paused || fs == State_Running)))
    03232                 return false;
    03233
    03234         if(fs == State_Running && fNeedsToPause)
    03235         {
    03236                 pMC->Pause();
    03237                 GetMediaState(); // wait for completion of the pause command
    03238         }
    03239
    03240         HRESULT hr;
    03241         CString errmsg;
    03242
    03243         do
    03244         {
    03245                 if(m_pCAP)
    03246                 {
    03247                         hr = m_pCAP->GetDIB(NULL, (DWORD*)&size);
    03248                         if(FAILED(hr)) {errmsg.Format(_T("GetDIB failed, hr = %08x"), hr); break;}
    03249
    03250                         if(!(*ppData = new BYTE[size])) return false;
    03251
    03252                         hr = m_pCAP->GetDIB(*ppData, (DWORD*)&size);
    03253                         if(FAILED(hr)) {errmsg.Format(_T("GetDIB failed, hr = %08x"), hr); break;}
    03254                 }
    03255                 else
    03256                 {
    03257                         hr = pBV->GetCurrentImage(&size, NULL);
    03258                         if(FAILED(hr) || size == 0) {errmsg.Format(_T("GetCurrentImage failed, hr = %08x"), hr); break;}
    03259
    03260                         if(!(*ppData = new BYTE[size])) return false;
    03261
    03262                         hr = pBV->GetCurrentImage(&size, (long*)*ppData);
    03263                         if(FAILED(hr)) {errmsg.Format(_T("GetCurrentImage failed, hr = %08x"), hr); break;}
    03264                 }
    03265         }
    03266         while(0);
    03267
    03268         if(!fSilent)
    03269         {
    03270                 if(!errmsg.IsEmpty())
    03271                 {
    03272                         AfxMessageBox(errmsg, MB_OK);
    03273                 }
    03274         }
    03275
    03276         if(fs == State_Running && GetMediaState() != State_Running)
    03277         {
    03278                 pMC->Run();
    03279         }
    03280
    03281         return !!*ppData;
    03282 }
    03283
    03284 #include "jpeg.h"
    03285
    03286 void CMainFrame::SaveImage(LPCTSTR fn)
    03287 {
    03288         BYTE* pData = NULL;
    03289         long size = 0;
    03290         if(GetDIB(&pData, size))
    03291         {
    03292                 CString ext = CString(CPath(fn).GetExtension()).MakeLower();
    03293
    03294                 if(ext == _T(".bmp"))
    03295                 {
    03296                         if(FILE* f = _tfopen(fn, _T("wb")))
    03297                         {
    03298                                 BITMAPINFO* bi = (BITMAPINFO*)pData;
    03299
    03300                                 BITMAPFILEHEADER bfh;
    03301                                 bfh.bfType = 'MB';
    03302                                 bfh.bfOffBits = sizeof(bfh) + sizeof(bi->bmiHeader);
    03303                                 bfh.bfSize = sizeof(bfh) + size;
    03304                                 bfh.bfReserved1 = bfh.bfReserved2 = 0;
    03305
    03306                                 if(bi->bmiHeader.biBitCount <= 8)
    03307                                 {
    03308                                         if(bi->bmiHeader.biClrUsed) bfh.bfOffBits += bi->bmiHeader.biClrUsed * sizeof(bi->bmiColors[0]);
    03309                                         else bfh.bfOffBits += (1 << bi->bmiHeader.biBitCount) * sizeof(bi->bmiColors[0]);
    03310                                 }
    03311
    03312                                 fwrite(&bfh, 1, sizeof(bfh), f);
    03313                                 fwrite(pData, 1, size, f);
    03314
    03315                                 fclose(f);
    03316                         }
    03317                         else
    03318                         {
    03319                                 AfxMessageBox(_T("Cannot create file"), MB_OK);
    03320                         }
    03321                 }
    03322                 else if(ext == _T(".jpg"))
    03323                 {
    03324                         CJpegEncoderFile(fn).Encode(pData);
    03325                 }
    03326
    03327                 delete [] pData;
    03328
    03329                 CPath p(fn);
    03330
    03331                 if(CDC* pDC = m_wndStatusBar.m_status.GetDC())
    03332                 {
    03333                         CRect r;
    03334                         m_wndStatusBar.m_status.GetClientRect(r);
    03335                         p.CompactPath(pDC->m_hDC, r.Width());
    03336                         m_wndStatusBar.m_status.ReleaseDC(pDC);
    03337                 }
    03338
    03339                 SendStatusMessage((LPCTSTR)p, 3000);
    03340         }
    03341 }
    03342
    03343 static CString MakeSnapshotFileName()
    03344 {
    03345         CTime t = CTime::GetCurrentTime();
    03346         CString fn;
    03347         fn.Format(_T("snapshot%s%s"),
    03348                 t.Format(_T("%Y%m%d%H%M%S")), AfxGetAppSettings().SnapShotExt);
    03349         return fn;
    03350 }
    03351
    03352 void CMainFrame::OnFileSaveImage()
    03353 {
    03354         AppSettings& s = AfxGetAppSettings();
    03355
    03356         CPath psrc(s.SnapShotPath);
    03357         psrc.Combine(s.SnapShotPath, MakeSnapshotFileName());
    03358
    03359         CFileDialog fd(FALSE, 0, (LPCTSTR)psrc,
    03360                 OFN_EXPLORER|OFN_ENABLESIZING|OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_PATHMUSTEXIST,
    03361                 _T("Bitmaps (*.bmp)|*.bmp|Jpeg (*.jpg)|*.jpg||"), this, 0);
    03362
    03363         if(s.SnapShotExt == _T(".bmp")) fd.m_pOFN->nFilterIndex = 1;
    03364         else if(s.SnapShotExt == _T(".jpg")) fd.m_pOFN->nFilterIndex = 2;
    03365
    03366         if(fd.DoModal() != IDOK) return;
    03367
    03368         if(fd.m_pOFN->nFilterIndex == 1) s.SnapShotExt = _T(".bmp");
    03369         else if(fd.m_pOFN->nFilterIndex = 2) s.SnapShotExt = _T(".jpg");
    03370
    03371         CPath pdst(fd.GetPathName());
    03372         pdst.AddExtension(s.SnapShotExt);
    03373         CString path = (LPCTSTR)pdst;
    03374         pdst.RemoveFileSpec();
    03375         s.SnapShotPath = (LPCTSTR)pdst;
    03376
    03377         SaveImage(path);
    03378 }
    03379
    03380 void CMainFrame::OnFileSaveImageAuto()
    03381 {
    03382         CString fn;
    03383         fn.Format(_T("%s\\%s"), AfxGetAppSettings().SnapShotPath, MakeSnapshotFileName());
    03384         SaveImage(fn);
    03385 }
    03386
    03387 void CMainFrame::OnUpdateFileSaveImage(CCmdUI* pCmdUI)
    03388 {
    03389         OAFilterState fs = GetMediaState();
    03390         pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly
    03391                 && (fs == State_Paused || fs == State_Running));
    03392 }
    03393
    03394 void CMainFrame::OnFileConvert()
    03395 {
    03396         CConvertDlg().DoModal();
    03397 }
    03398
    03399 void CMainFrame::OnUpdateFileConvert(CCmdUI* pCmdUI)
    03400 {
    03401         // TODO: Add your command update UI handler code here
    03402 }
    03403
    03404 void CMainFrame::OnFileLoadsubtitles()
    03405 {
    03406         if(!m_pCAP)
    03407         {
    03408                 AfxMessageBox(_T("To load subtitles you have change the video renderer type and reopen the file.\n")
    03409                                         _T("- DirectShow: VMR7 or VMR9 renderless\n")
    03410                                         _T("- RealMedia: Special renderer for RealMedia, or open it through DirectShow\n")
    03411                                         _T("- Quicktime: DX7 or DX9 renderer for QuickTime\n")
    03412                                         _T("- ShockWave: n/a\n")
    03413                                         , MB_OK);
    03414                 return;
    03415         }
    03416
    03417         static TCHAR BASED_CODE szFilter[] =
    03418                 _T(".srt .sub .ssa .ass .smi .psb .txt .idx .usf .xss|")
    03419                 _T("*.srt;*.sub;*.ssa;*.ass;*smi;*.psb;*.txt;*.idx;*.usf;*.xss||");
    03420
    03421         CFileDialog fd(TRUE, NULL, NULL,
    03422                 OFN_EXPLORER | OFN_ENABLESIZING | OFN_HIDEREADONLY,
    03423                 szFilter, this, 0);
    03424
    03425         if(fd.DoModal() != IDOK) return;
    03426
    03427         if(LoadSubtitle(fd.GetPathName()))
    03428                 SetSubtitle(m_pSubStreams.GetTail());
    03429 }
    03430
    03431 void CMainFrame::OnUpdateFileLoadsubtitles(CCmdUI *pCmdUI)
    03432 {
    03433         pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && /*m_pCAP &&*/ !m_fAudioOnly);
    03434 }
    03435
    03436 void CMainFrame::OnFileSavesubtitles()
    03437 {
    03438         int i = m_iSubtitleSel;
    03439
    03440         POSITION pos = m_pSubStreams.GetHeadPosition();
    03441         while(pos && i >= 0)
    03442         {
    03443                 CComPtr<ISubStream> pSubStream = m_pSubStreams.GetNext(pos);
    03444
    03445                 if(i < pSubStream->GetStreamCount())
    03446                 {
    03447                         CLSID clsid;
    03448                         if(FAILED(pSubStream->GetClassID(&clsid)))
    03449                                 continue;
    03450
    03451                         if(clsid == __uuidof(CVobSubFile))
    03452                         {
    03453                                 CVobSubFile* pVSF = (CVobSubFile*)(ISubStream*)pSubStream;
    03454
    03455                                 CFileDialog fd(FALSE, NULL, NULL,
    03456                                         OFN_EXPLORER|OFN_ENABLESIZING|OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_PATHMUSTEXIST,
    03457                                         _T("VobSub (*.idx, *.sub)|*.idx;*.sub||"), this, 0);
    03458
    03459                                 if(fd.DoModal() == IDOK)
    03460                                 {
    03461                                         CAutoLock cAutoLock(&m_csSubLock);
    03462                                         pVSF->Save(fd.GetPathName());
    03463                                 }
    03464
    03465                                 return;
    03466                         }
    03467                         else if(clsid == __uuidof(CRenderedTextSubtitle))
    03468                         {
    03469                                 CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)pSubStream;
    03470
    03471                                 CString filter;
    03472                                 filter += _T("Subripper (*.srt)|*.srt|");
    03473                                 filter += _T("Microdvd (*.sub)|*.sub|");
    03474                                 filter += _T("Sami (*.smi)|*.smi|");
    03475                                 filter += _T("Psb (*.psb)|*.psb|");
    03476                                 filter += _T("Sub Station Alpha (*.ssa)|*.ssa|");
    03477                                 filter += _T("Advanced Sub Station Alpha (*.ass)|*.ass|");
    03478                                 filter += _T("|");
    03479
    03480                                 CSaveTextFileDialog fd(pRTS->m_encoding, NULL, NULL, filter, this);
    03481
    03482                                 if(fd.DoModal() == IDOK)
    03483                                 {
    03484                                         CAutoLock cAutoLock(&m_csSubLock);
    03485                                         pRTS->SaveAs(fd.GetPathName(), (exttype)(fd.m_ofn.nFilterIndex-1), m_pCAP->GetFPS(), fd.GetEncoding());
    03486                                 }
    03487
    03488                                 return;
    03489                         }
    03490                 }
    03491
    03492                 i -= pSubStream->GetStreamCount();
    03493         }
    03494 }
    03495
    03496 void CMainFrame::OnUpdateFileSavesubtitles(CCmdUI* pCmdUI)
    03497 {
    03498         pCmdUI->Enable(m_iSubtitleSel >= 0);
    03499 }
    03500
    03502
    03503 #include "SubtitleDlDlg.h"
    03504 #include "ISDb.h"
    03505
    03506 void CMainFrame::OnSubtitledatabaseSearch()
    03507 {
    03508         CStringA url = "http://" + AfxGetAppSettings().ISDb + "/index.php?";
    03509         CStringA args = makeargs(m_wndPlaylistBar.m_pl);
    03510         ShellExecute(m_hWnd, _T("open"), CString(url+args), NULL, NULL, SW_SHOWDEFAULT);
    03511 }
    03512
    03513 void CMainFrame::OnUpdateSubtitledatabaseSearch(CCmdUI *pCmdUI)
    03514 {
    03515         pCmdUI->Enable(TRUE);
    03516 }
    03517
    03518 void CMainFrame::OnSubtitledatabaseUpload()
    03519 {
    03520         CStringA url = "http://" + AfxGetAppSettings().ISDb + "/ul.php?";
    03521         CStringA args = makeargs(m_wndPlaylistBar.m_pl);
    03522         ShellExecute(m_hWnd, _T("open"), CString(url+args), NULL, NULL, SW_SHOWDEFAULT);
    03523 }
    03524
    03525 void CMainFrame::OnUpdateSubtitledatabaseUpload(CCmdUI *pCmdUI)
    03526 {
    03527         pCmdUI->Enable(m_wndPlaylistBar.GetCount() > 0);
    03528 }
    03529
    03530 void CMainFrame::OnSubtitledatabaseDownload()
    03531 {
    03532         filehash fh;
    03533         if(!hash(m_wndPlaylistBar.GetCur(), fh))
    03534         {
    03535                 MessageBeep(-1);
    03536                 return;
    03537         }
    03538
    03539         // TODO: put this on a worker thread
    03540
    03541         CStringA url = "http://" + AfxGetAppSettings().ISDb + "/index.php?";
    03542         CStringA args;
    03543         args.Format("player=mpc&name[0]=%s&size[0]=%016I64x&hash[0]=%016I64x",
    03544                 UrlEncode(CStringA(fh.name)), fh.size, fh.hash);
    03545
    03546         try
    03547         {
    03548                 CInternetSession is;
    03549
    03550                 CStringA str;
    03551                 if(!OpenUrl(is, CString(url+args), str))
    03552                 {
    03553                         MessageBeep(-1);
    03554                         return;
    03555                 }
    03556
    03557                 CStringA ticket;
    03558                 CList<isdb_movie> movies;
    03559                 isdb_movie m;
    03560                 isdb_subtitle s;
    03561
    03562                 CList<CStringA> sl;
    03563                 Explode(str, sl, '\n');
    03564
    03565                 POSITION pos = sl.GetHeadPosition();
    03566                 while(pos)
    03567                 {
    03568                         str = sl.GetNext(pos);
    03569
    03570                         CStringA param = str.Left(max(0, str.Find('=')));
    03571                         CStringA value = str.Mid(str.Find('=')+1);
    03572
    03573                         if(param == "ticket") ticket = value;
    03574                         else if(param == "movie") {m.reset(); Explode(value, m.titles, '|');}
    03575                         else if(param == "subtitle") {s.reset(); s.id = atoi(value);}
    03576                         else if(param == "name") s.name = value;
    03577                         else if(param == "discs") s.discs = atoi(value);
    03578                         else if(param == "disc_no") s.disc_no = atoi(value);
    03579                         else if(param == "format") s.format = value;
    03580                         else if(param == "iso639_2") s.iso639_2 = value;
    03581                         else if(param == "language") s.language = value;
    03582                         else if(param == "nick") s.nick = value;
    03583                         else if(param == "email") s.email = value;
    03584                         else if(param == "" && value == "endsubtitle") {m.subs.AddTail(s);}
    03585                         else if(param == "" && value == "endmovie") {movies.AddTail(m);}
    03586                         else if(param == "" && value == "end") break;
    03587                 }
    03588
    03589                 CSubtitleDlDlg dlg(movies, this);
    03590                 if(IDOK == dlg.DoModal())
    03591                 {
    03592                         if(dlg.m_fReplaceSubs)
    03593                                 m_pSubStreams.RemoveAll();
    03594
    03595                         CComPtr<ISubStream> pSubStreamToSet;
    03596
    03597                         POSITION pos = dlg.m_selsubs.GetHeadPosition();
    03598                         while(pos)
    03599                         {
    03600                                 isdb_subtitle& s = dlg.m_selsubs.GetNext(pos);
    03601
    03602                                 CStringA url = "http://" + AfxGetAppSettings().ISDb + "/dl.php?";
    03603                                 CStringA args;
    03604                                 args.Format("id=%d&ticket=%s", s.id, UrlEncode(ticket));
    03605
    03606                                 if(OpenUrl(is, CString(url+args), str))
    03607                                 {
    03608                                         CAutoPtr<CRenderedTextSubtitle> pRTS(new CRenderedTextSubtitle(&m_csSubLock));
    03609                                         if(pRTS && pRTS->Open((BYTE*)(LPCSTR)str, str.GetLength(), DEFAULT_CHARSET, CString(s.name)) && pRTS->GetStreamCount() > 0)
    03610                                         {
    03611                                                 CComPtr<ISubStream> pSubStream = pRTS.Detach();
    03612                                                 m_pSubStreams.AddTail(pSubStream);
    03613                                                 if(!pSubStreamToSet) pSubStreamToSet = pSubStream;
    03614                                         }
    03615                                 }
    03616                         }
    03617
    03618                         if(pSubStreamToSet)
    03619                                 SetSubtitle(pSubStreamToSet);
    03620                 }
    03621         }
    03622         catch(CInternetException* ie)
    03623         {
    03624                 ie->Delete();
    03625                 return;
    03626         }
    03627 }
    03628
    03629 void CMainFrame::OnUpdateSubtitledatabaseDownload(CCmdUI *pCmdUI)
    03630 {
    03631         pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && m_pCAP && !m_fAudioOnly);
    03632 }
    03633
    03634 void CMainFrame::OnFileProperties()
    03635 {
    03636         CPPageFileInfoSheet m_fileinfo(m_wndPlaylistBar.GetCur(), this);
    03637         m_fileinfo.DoModal();
    03638 }
    03639
    03640 void CMainFrame::OnUpdateFileProperties(CCmdUI* pCmdUI)
    03641 {
    03642         pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && m_iPlaybackMode == PM_FILE);
    03643 }
    03644
    03645 void CMainFrame::OnFileCloseMedia()
    03646 {
    03647         CloseMedia();
    03648 }
    03649
    03650 void CMainFrame::OnFileClosePlaylist()
    03651 {
    03652         SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
    03653         RestoreDefaultWindowRect();
    03654 }
    03655
    03656 void CMainFrame::OnUpdateFileClose(CCmdUI* pCmdUI)
    03657 {
    03658         pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED || m_iMediaLoadState == MLS_LOADING);
    03659 }
    03660
    03661 // view
    03662
    03663 void CMainFrame::OnViewCaptionmenu()
    03664 {
    03665         bool fHideCaptionMenu = AfxGetAppSettings().fHideCaptionMenu;
    03666
    03667         AfxGetAppSettings().fHideCaptionMenu = !fHideCaptionMenu;
    03668
    03669         if(m_fFullScreen) return;
    03670
    03671         DWORD dwRemove = 0, dwAdd = 0;
    03672         HMENU hMenu;
    03673
    03674         if(!fHideCaptionMenu)
    03675         {
    03676                 dwRemove = WS_CAPTION;
    03677                 hMenu = NULL;
    03678         }
    03679         else
    03680         {
    03681                 dwAdd = WS_CAPTION;
    03682                 hMenu = m_hMenuDefault;
    03683         }
    03684
    03685         ModifyStyle(dwRemove, dwAdd, SWP_NOZORDER);
    03686         ::SetMenu(m_hWnd, hMenu);
    03687         SetWindowPos(NULL, 0, 0, 0, 0, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER);
    03688
    03689         MoveVideoWindow();
    03690 }
    03691
    03692 void CMainFrame::OnUpdateViewCaptionmenu(CCmdUI* pCmdUI)
    03693 {
    03694         pCmdUI->SetCheck(!AfxGetAppSettings().fHideCaptionMenu);
    03695 }
    03696
    03697 void CMainFrame::OnViewControlBar(UINT nID)
    03698 {
    03699         nID -= ID_VIEW_SEEKER;
    03700         ShowControls(AfxGetAppSettings().nCS ^ (1<<nID));
    03701 }
    03702
    03703 void CMainFrame::OnUpdateViewControlBar(CCmdUI* pCmdUI)
    03704 {
    03705         UINT nID = pCmdUI->m_nID - ID_VIEW_SEEKER;
    03706         pCmdUI->SetCheck(!!(AfxGetAppSettings().nCS & (1<<nID)));
    03707 }
    03708
    03709 void CMainFrame::OnViewSubresync()
    03710 {
    03711         ShowControlBar(&m_wndSubresyncBar, !m_wndSubresyncBar.IsWindowVisible(), TRUE);
    03712 }
    03713
    03714 void CMainFrame::OnUpdateViewSubresync(CCmdUI* pCmdUI)
    03715 {
    03716         pCmdUI->SetCheck(m_wndSubresyncBar.IsWindowVisible());
    03717         pCmdUI->Enable(m_pCAP && m_iSubtitleSel >= 0);
    03718 }
    03719
    03720 void CMainFrame::OnViewPlaylist()
    03721 {
    03722         ShowControlBar(&m_wndPlaylistBar, !m_wndPlaylistBar.IsWindowVisible(), TRUE);
    03723 }
    03724
    03725 void CMainFrame::OnUpdateViewPlaylist(CCmdUI* pCmdUI)
    03726 {
    03727         pCmdUI->SetCheck(m_wndPlaylistBar.IsWindowVisible());
    03728         pCmdUI->Enable(m_iMediaLoadState == MLS_CLOSED && m_iMediaLoadState != MLS_LOADED
    03729                 || m_iMediaLoadState == MLS_LOADED /*&& (m_iPlaybackMode == PM_FILE || m_iPlaybackMode == PM_CAPTURE)*/);
    03730 }
    03731
    03732 void CMainFrame::OnViewCapture()
    03733 {
    03734         ShowControlBar(&m_wndCaptureBar, !m_wndCaptureBar.IsWindowVisible(), TRUE);
    03735 }
    03736
    03737 void CMainFrame::OnUpdateViewCapture(CCmdUI* pCmdUI)
    03738 {
    03739         pCmdUI->SetCheck(m_wndCaptureBar.IsWindowVisible());
    03740         pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && m_iPlaybackMode == PM_CAPTURE);
    03741 }
    03742
    03743 void CMainFrame::OnViewMinimal()
    03744 {
    03745         if(!AfxGetAppSettings().fHideCaptionMenu)
    03746                 SendMessage(WM_COMMAND, ID_VIEW_CAPTIONMENU);
    03747         ShowControls(0);
    03748 }
    03749
    03750 void CMainFrame::OnUpdateViewMinimal(CCmdUI* pCmdUI)
    03751 {
    03752 }
    03753
    03754 void CMainFrame::OnViewCompact()
    03755 {
    03756         if(AfxGetAppSettings().fHideCaptionMenu)
    03757                 SendMessage(WM_COMMAND, ID_VIEW_CAPTIONMENU);
    03758         ShowControls(CS_TOOLBAR);
    03759 }
    03760
    03761 void CMainFrame::OnUpdateViewCompact(CCmdUI* pCmdUI)
    03762 {
    03763 }
    03764
    03765 void CMainFrame::OnViewNormal()
    03766 {
    03767         if(AfxGetAppSettings().fHideCaptionMenu)
    03768                 SendMessage(WM_COMMAND, ID_VIEW_CAPTIONMENU);
    03769         ShowControls(CS_SEEKBAR|CS_TOOLBAR|CS_STATUSBAR|CS_INFOBAR);
    03770 }
    03771
    03772 void CMainFrame::OnUpdateViewNormal(CCmdUI* pCmdUI)
    03773 {
    03774 }
    03775
    03776 void CMainFrame::OnViewFullscreen()
    03777 {
    03778         ToggleFullscreen(true, true);
    03779 }
    03780
    03781 void CMainFrame::OnViewFullscreenSecondary()
    03782 {
    03783         ToggleFullscreen(true, false);
    03784 }
    03785
    03786 void CMainFrame::OnUpdateViewFullscreen(CCmdUI* pCmdUI)
    03787 {
    03788         pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly || m_fFullScreen);
    03789         pCmdUI->SetCheck(m_fFullScreen);
    03790 }
    03791
    03792 void CMainFrame::OnViewZoom(UINT nID)
    03793 {
    03794         ZoomVideoWindow(nID == ID_VIEW_ZOOM_50 ? 0.5 : nID == ID_VIEW_ZOOM_200 ? 2.0 : 1.0);
    03795 }
    03796
    03797 void CMainFrame::OnUpdateViewZoom(CCmdUI* pCmdUI)
    03798 {
    03799         pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly);
    03800 }
    03801
    03802 void CMainFrame::OnViewDefaultVideoFrame(UINT nID)
    03803 {
    03804         AfxGetAppSettings().iDefaultVideoSize = nID - ID_VIEW_VF_HALF;
    03805         m_ZoomX = m_ZoomY = 1;
    03806         m_PosX = m_PosY = 0.5;
    03807         MoveVideoWindow();
    03808 }
    03809
    03810 void CMainFrame::OnUpdateViewDefaultVideoFrame(CCmdUI* pCmdUI)
    03811 {
    03812         pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly);
    03813         pCmdUI->SetRadio(AfxGetAppSettings().iDefaultVideoSize == (pCmdUI->m_nID - ID_VIEW_VF_HALF));
    03814 }
    03815
    03816 void CMainFrame::OnViewKeepaspectratio()
    03817 {
    03818         AfxGetAppSettings().fKeepAspectRatio = !AfxGetAppSettings().fKeepAspectRatio;
    03819         MoveVideoWindow();
    03820 }
    03821
    03822 void CMainFrame::OnUpdateViewKeepaspectratio(CCmdUI* pCmdUI)
    03823 {
    03824         pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly);
    03825         pCmdUI->SetCheck(AfxGetAppSettings().fKeepAspectRatio);
    03826 }
    03827
    03828 void CMainFrame::OnViewCompMonDeskARDiff()
    03829 {
    03830         AfxGetAppSettings().fCompMonDeskARDiff = !AfxGetAppSettings().fCompMonDeskARDiff;
    03831         MoveVideoWindow();
    03832 }
    03833
    03834 void CMainFrame::OnUpdateViewCompMonDeskARDiff(CCmdUI* pCmdUI)
    03835 {
    03836         pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly);
    03837         pCmdUI->SetCheck(AfxGetAppSettings().fCompMonDeskARDiff);
    03838 }
    03839
    03840 void CMainFrame::OnViewPanNScan(UINT nID)
    03841 {
    03842         if(m_iMediaLoadState != MLS_LOADED) return;
    03843
    03844         int x = 0, y = 0;
    03845         int dx = 0, dy = 0;
    03846
    03847         switch(nID)
    03848         {
    03849         case ID_VIEW_RESET: m_ZoomX = m_ZoomY = 1.0; m_PosX = m_PosY = 0.5; m_AngleX = m_AngleY = m_AngleZ = 0; break;
    03850         case ID_VIEW_INCSIZE: x = y = 1; break;
    03851         case ID_VIEW_DECSIZE: x = y = -1; break;
    03852         case ID_VIEW_INCWIDTH: x = 1; break;
    03853         case ID_VIEW_DECWIDTH: x = -1; break;
    03854         case ID_VIEW_INCHEIGHT: y = 1; break;
    03855         case ID_VIEW_DECHEIGHT: y = -1; break;
    03856         case ID_PANSCAN_CENTER: m_PosX = m_PosY = 0.5; break;
    03857         case ID_PANSCAN_MOVELEFT: dx = -1; break;
    03858         case ID_PANSCAN_MOVERIGHT: dx = 1; break;
    03859         case ID_PANSCAN_MOVEUP: dy = -1; break;
    03860         case ID_PANSCAN_MOVEDOWN: dy = 1; break;
    03861         case ID_PANSCAN_MOVEUPLEFT: dx = dy = -1; break;
    03862         case ID_PANSCAN_MOVEUPRIGHT: dx = 1; dy = -1; break;
    03863         case ID_PANSCAN_MOVEDOWNLEFT: dx = -1; dy = 1; break;
    03864         case ID_PANSCAN_MOVEDOWNRIGHT: dx = dy = 1; break;
    03865         default: break;
    03866         }
    03867
    03868         if(x > 0 && m_ZoomX < 3) m_ZoomX *= 1.02;
    03869         if(x < 0 && m_ZoomX > 0.2) m_ZoomX /= 1.02;
    03870         if(y > 0 && m_ZoomY < 3) m_ZoomY *= 1.02;
    03871         if(y < 0 && m_ZoomY > 0.2) m_ZoomY /= 1.02;
    03872
    03873         if(dx < 0 && m_PosX > 0) m_PosX = max(m_PosX - 0.005*m_ZoomX, 0);
    03874         if(dx > 0 && m_PosX < 1) m_PosX = min(m_PosX + 0.005*m_ZoomX, 1);
    03875         if(dy < 0 && m_PosY > 0) m_PosY = max(m_PosY - 0.005*m_ZoomY, 0);
    03876         if(dy > 0 && m_PosY < 1) m_PosY = min(m_PosY + 0.005*m_ZoomY, 1);
    03877
    03878         MoveVideoWindow(true);
    03879
    03880         if(nID == ID_VIEW_RESET && m_pCAP)
    03881         {
    03882                 m_pCAP->SetVideoAngle(Vector(DegToRad(m_AngleX), DegToRad(m_AngleY), DegToRad(m_AngleZ)));
    03883         }
    03884 }
    03885
    03886 void CMainFrame::OnUpdateViewPanNScan(CCmdUI* pCmdUI)
    03887 {
    03888         pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly);
    03889 }
    03890
    03891 void CMainFrame::OnViewPanNScanPresets(UINT nID)
    03892 {
    03893         if(m_iMediaLoadState != MLS_LOADED) return;
    03894
    03895         AppSettings& s = AfxGetAppSettings();
    03896
    03897         nID -= ID_PANNSCAN_PRESETS_START;
    03898
    03899         if(nID == s.m_pnspresets.GetCount())
    03900         {
    03901                 CPnSPresetsDlg dlg;
    03902                 dlg.m_pnspresets.Copy(s.m_pnspresets);
    03903                 if(dlg.DoModal() == IDOK)
    03904                 {
    03905                         s.m_pnspresets.Copy(dlg.m_pnspresets);
    03906                         s.UpdateData(true);
    03907                 }
    03908                 return;
    03909         }
    03910
    03911         m_PosX = 0.5;
    03912         m_PosY = 0.5;
    03913         m_ZoomX = 1.0;
    03914         m_ZoomY = 1.0;
    03915
    03916         CString str = s.m_pnspresets[nID];
    03917
    03918         int i = 0, j = 0;
    03919         for(CString token = str.Tokenize(_T(","), i); !token.IsEmpty(); token = str.Tokenize(_T(","), i), j++)
    03920         {
    03921                 float f = 0;
    03922                 if(_stscanf(token, _T("%f"), &f) != 1) continue;
    03923
    03924                 switch(j)
    03925                 {
    03926                 case 0: break;
    03927                 case 1: m_PosX = f; break;
    03928                 case 2: m_PosY = f; break;
    03929                 case 3: m_ZoomX = f; break;
    03930                 case 4: m_ZoomY = f; break;
    03931                 default: break;
    03932                 }
    03933         }
    03934
    03935         if(j != 5) return;
    03936
    03937         m_PosX = min(max(m_PosX, 0), 1);
    03938         m_PosY = min(max(m_PosY, 0), 1);
    03939         m_ZoomX = min(max(m_ZoomX, 0.2), 3);
    03940         m_ZoomY = min(max(m_ZoomY, 0.2), 3);
    03941
    03942         MoveVideoWindow(true);
    03943 }
    03944
    03945 void CMainFrame::OnUpdateViewPanNScanPresets(CCmdUI* pCmdUI)
    03946 {
    03947         int nID = pCmdUI->m_nID - ID_PANNSCAN_PRESETS_START;
    03948         AppSettings& s = AfxGetAppSettings();
    03949         pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly && nID >= 0 && nID <= s.m_pnspresets.GetCount());
    03950 }
    03951
    03952 void CMainFrame::OnViewRotate(UINT nID)
    03953 {
    03954         if(!m_pCAP) return;
    03955
    03956         switch(nID)
    03957         {
    03958         case ID_PANSCAN_ROTATEXP: m_AngleX += 2; break;
    03959         case ID_PANSCAN_ROTATEXM: m_AngleX -= 2; break;
    03960         case ID_PANSCAN_ROTATEYP: m_AngleY += 2; break;
    03961         case ID_PANSCAN_ROTATEYM: m_AngleY -= 2; break;
    03962         case ID_PANSCAN_ROTATEZP: m_AngleZ += 2; break;
    03963         case ID_PANSCAN_ROTATEZM: m_AngleZ -= 2; break;
    03964         default: return;
    03965         }
    03966
    03967         m_pCAP->SetVideoAngle(Vector(DegToRad(m_AngleX), DegToRad(m_AngleY), DegToRad(m_AngleZ)));
    03968
    03969         CString info;
    03970         info.Format(_T("x: %d, y: %d, z: %d"), m_AngleX, m_AngleY, m_AngleZ);
    03971         SendStatusMessage(info, 3000);
    03972 }
    03973
    03974 void CMainFrame::OnUpdateViewRotate(CCmdUI* pCmdUI)
    03975 {
    03976         pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly && m_pCAP);
    03977 }
    03978
    03979 void CMainFrame::OnViewAspectRatio(UINT nID)
    03980 {
    03981         CSize& ar = AfxGetAppSettings().AspectRatio;
    03982
    03983         switch(nID)
    03984         {
    03985         default: ar.SetSize(0, 0); break;
    03986         case ID_ASPECTRATIO_4: ar.SetSize(4, 3); break;
    03987         case ID_ASPECTRATIO_5: ar.SetSize(5, 4); break;
    03988         case ID_ASPECTRATIO_16: ar.SetSize(16, 9); break;
    03989         }
    03990
    03991         CString info;
    03992         if(ar.cx && ar.cy) info.Format(_T("Aspect Ratio: %d:%d"), ar.cx, ar.cy);
    03993         else info.Format(_T("Aspect Ratio: Default"));
    03994         SendStatusMessage(info, 3000);
    03995
    03996         MoveVideoWindow();
    03997 }
    03998
    03999 void CMainFrame::OnUpdateViewAspectRatio(CCmdUI* pCmdUI)
    04000 {
    04001         const CSize& ar = AfxGetAppSettings().AspectRatio;
    04002
    04003         switch(pCmdUI->m_nID)
    04004         {
    04005         default: pCmdUI->SetRadio(ar == CSize(0, 0)); break;
    04006         case ID_ASPECTRATIO_4: pCmdUI->SetRadio(ar == CSize(4, 3)); break;
    04007         case ID_ASPECTRATIO_5: pCmdUI->SetRadio(ar == CSize(5, 4)); break;
    04008         case ID_ASPECTRATIO_16: pCmdUI->SetRadio(ar == CSize(16, 9)); break;
    04009         }
    04010
    04011         pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly);
    04012 }
    04013
    04014 void CMainFrame::OnViewOntop(UINT nID)
    04015 {
    04016         nID -= ID_ONTOP_NEVER;
    04017         if(AfxGetAppSettings().iOnTop == nID)
    04018                 nID = !nID;
    04019         SetAlwaysOnTop(nID);
    04020 }
    04021
    04022 void CMainFrame::OnUpdateViewOntop(CCmdUI* pCmdUI)
    04023 {
    04024         pCmdUI->SetRadio(AfxGetAppSettings().iOnTop == (pCmdUI->m_nID - ID_ONTOP_NEVER));
    04025 }
    04026
    04027 void CMainFrame::OnViewOptions()
    04028 {
    04029         ShowOptions();
    04030 }
    04031
    04032 // play
    04033
    04034 void CMainFrame::OnPlayPlay()
    04035 {
    04036         if(m_iMediaLoadState == MLS_LOADED)
    04037         {
    04038                 if(GetMediaState() == State_Stopped) m_iSpeedLevel = 0;
    04039
    04040                 if(m_iPlaybackMode == PM_FILE)
    04041                 {
    04042                         if(m_fEndOfStream) SendMessage(WM_COMMAND, ID_PLAY_STOP);
    04043                         pMC->Run();
    04044                 }
    04045                 else if(m_iPlaybackMode == PM_DVD)
    04046                 {
    04047                         double dRate = 1.0;
    04048                         if(m_iSpeedLevel != -4 && m_iSpeedLevel != 0)
    04049                                 dRate = pow(2.0, m_iSpeedLevel >= -3 ? m_iSpeedLevel : (-m_iSpeedLevel - 8));
    04050
    04051                         pDVDC->PlayForwards(dRate, DVD_CMD_FLAG_Block, NULL);
    04052                         pDVDC->Pause(FALSE);
    04053                         pMC->Run();
    04054                 }
    04055                 else if(m_iPlaybackMode == PM_CAPTURE)
    04056                 {
    04057                         pMC->Stop(); // audio preview won't be in sync if we run it from paused state
    04058                         pMC->Run();
    04059                 }
    04060
    04061                 SetTimer(TIMER_STREAMPOSPOLLER, 40, NULL);
    04062                 SetTimer(TIMER_STREAMPOSPOLLER2, 500, NULL);
    04063                 SetTimer(TIMER_STATS, 1000, NULL);
    04064
    04065                 if(m_fFrameSteppingActive) // FIXME
    04066                 {
    04067                         m_fFrameSteppingActive = false;
    04068                         pBA->put_Volume(m_VolumeBeforeFrameStepping);
    04069                 }
    04070
    04071                 SetAlwaysOnTop(AfxGetAppSettings().iOnTop);
    04072         }
    04073
    04074         MoveVideoWindow();
    04075 }
    04076
    04077 void CMainFrame::OnPlayPause()
    04078 {
    04079         if(m_iMediaLoadState == MLS_LOADED)
    04080         {
    04081                 SetAlwaysOnTop(AfxGetAppSettings().iOnTop);
    04082
    04083                 if(m_iPlaybackMode == PM_FILE)
    04084                 {
    04085                         pMC->Pause();
    04086                 }
    04087                 else if(m_iPlaybackMode == PM_DVD)
    04088                 {
    04089                         pMC->Pause();
    04090                 }
    04091                 else if(m_iPlaybackMode == PM_CAPTURE)
    04092                 {
    04093                         pMC->Pause();
    04094                 }
    04095
    04096                 SetTimer(TIMER_STREAMPOSPOLLER, 40, NULL);
    04097                 SetTimer(TIMER_STREAMPOSPOLLER2, 500, NULL);
    04098                 SetTimer(TIMER_STATS, 1000, NULL);
    04099         }
    04100
    04101         MoveVideoWindow();
    04102 }
    04103
    04104 void CMainFrame::OnPlayPlaypause()
    04105 {
    04106         OAFilterState fs = GetMediaState();
    04107         if(fs == State_Running) SendMessage(WM_COMMAND, ID_PLAY_PAUSE);
    04108         else if(fs == State_Stopped || fs == State_Paused) SendMessage(WM_COMMAND, ID_PLAY_PLAY);
    04109 }
    04110
    04111 void CMainFrame::OnPlayStop()
    04112 {
    04113         if(m_iMediaLoadState == MLS_LOADED)
    04114         {
    04115                 if(m_iPlaybackMode == PM_FILE)
    04116                 {
    04117                         LONGLONG pos = 0;
    04118                         pMS->SetPositions(&pos, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning);
    04119                         pMC->Stop();
    04120
    04121                         // BUG: after pause or stop the netshow url source filter won't continue
    04122                         // on the next play command, unless we cheat it by setting the file name again.
    04123                         //
    04124                         // Note: WMPx may be using some undocumented interface to restart streaming.
    04125
    04126                         BeginEnumFilters(pGB, pEF, pBF)
    04127                         {
    04128                                 CComQIPtr<IAMNetworkStatus, &IID_IAMNetworkStatus> pAMNS = pBF;
    04129                                 CComQIPtr<IFileSourceFilter> pFSF = pBF;
    04130                                 if(pAMNS && pFSF)
    04131                                 {
    04132                                         WCHAR* pFN = NULL;
    04133                                         AM_MEDIA_TYPE mt;
    04134                                         if(SUCCEEDED(pFSF->GetCurFile(&pFN, &mt)) && pFN && *pFN)
    04135                                         {
    04136                                                 pFSF->Load(pFN, NULL);
    04137                                                 CoTaskMemFree(pFN);
    04138                                         }
    04139                                         break;
    04140                                 }
    04141                         }
    04142                         EndEnumFilters
    04143                 }
    04144                 else if(m_iPlaybackMode == PM_DVD)
    04145                 {
    04146                         pDVDC->SetOption(DVD_ResetOnStop, TRUE);
    04147                         pMC->Stop();
    04148                         pDVDC->SetOption(DVD_ResetOnStop, FALSE);
    04149                 }
    04150                 else if(m_iPlaybackMode == PM_CAPTURE)
    04151                 {
    04152                         pMC->Stop();
    04153                 }
    04154
    04155                 m_iSpeedLevel = 0;
    04156
    04157                 if(m_fFrameSteppingActive) // FIXME
    04158                 {
    04159                         m_fFrameSteppingActive = false;
    04160                         pBA->put_Volume(m_VolumeBeforeFrameStepping);
    04161                 }
    04162
    04163                 m_fEndOfStream = false;
    04164         }
    04165
    04166         m_nLoops = 0;
    04167
    04168         if(m_hWnd)
    04169         {
    04170                 KillTimer(TIMER_STREAMPOSPOLLER2);
    04171                 KillTimer(TIMER_STREAMPOSPOLLER);
    04172                 KillTimer(TIMER_STATS);
    04173
    04174                 MoveVideoWindow();
    04175
    04176                 if(m_iMediaLoadState == MLS_LOADED)
    04177                 {
    04178                         __int64 start, stop;
    04179                         m_wndSeekBar.GetRange(start, stop);
    04180                         GUID tf;
    04181                         pMS->GetTimeFormat(&tf);
    04182                         m_wndStatusBar.SetStatusTimer(m_wndSeekBar.GetPosReal(), stop, !!m_wndSubresyncBar.IsWindowVisible(), &tf);
    04183
    04184                         SetAlwaysOnTop(AfxGetAppSettings().iOnTop);
    04185                 }
    04186         }
    04187 }
    04188
    04189 void CMainFrame::OnUpdatePlayPauseStop(CCmdUI* pCmdUI)
    04190 {
    04191         OAFilterState fs = m_fFrameSteppingActive ? State_Paused : GetMediaState();
    04192
    04193         pCmdUI->SetCheck(fs == State_Running && pCmdUI->m_nID == ID_PLAY_PLAY
    04194                 || fs == State_Paused && pCmdUI->m_nID == ID_PLAY_PAUSE
    04195                 || fs == State_Stopped && pCmdUI->m_nID == ID_PLAY_STOP
    04196                 || (fs == State_Paused || fs == State_Running) && pCmdUI->m_nID == ID_PLAY_PLAYPAUSE);
    04197
    04198         bool fEnable = false;
    04199
    04200         if(fs >= 0)
    04201         {
    04202                 if(m_iPlaybackMode == PM_FILE || m_iPlaybackMode == PM_CAPTURE)
    04203                 {
    04204                         fEnable = true;
    04205
    04206                         if(fs == State_Stopped && pCmdUI->m_nID == ID_PLAY_PAUSE && m_fRealMediaGraph) fEnable = false; // can't go into paused state from stopped with rm
    04207                         else if(m_fCapturing) fEnable = false;
    04208                         else if(m_fLiveWM && pCmdUI->m_nID == ID_PLAY_PAUSE) fEnable = false;
    04209                 }
    04210                 else if(m_iPlaybackMode == PM_DVD)
    04211                 {
    04212                         fEnable = m_iDVDDomain != DVD_DOMAIN_VideoManagerMenu
    04213                                 && m_iDVDDomain != DVD_DOMAIN_VideoTitleSetMenu;
    04214
    04215                         if(fs == State_Stopped && pCmdUI->m_nID == ID_PLAY_PAUSE) fEnable = false;
    04216                 }
    04217         }
    04218
    04219         pCmdUI->Enable(fEnable);
    04220 }
    04221
    04222 void CMainFrame::OnPlayFramestep(UINT nID)
    04223 {
    04224         REFERENCE_TIME rt;
    04225
    04226         if(pFS && m_fQuicktimeGraph)
    04227         {
    04228                 if(GetMediaState() != State_Paused)
    04229                         SendMessage(WM_COMMAND, ID_PLAY_PAUSE);
    04230
    04231                 pFS->Step(nID == ID_PLAY_FRAMESTEP ? 1 : -1, NULL);
    04232         }
    04233         else if(pFS && nID == ID_PLAY_FRAMESTEP)
    04234         {
    04235                 if(GetMediaState() != State_Paused)
    04236                         SendMessage(WM_COMMAND, ID_PLAY_PAUSE);
    04237
    04238                 m_fFrameSteppingActive = true;
    04239
    04240                 m_VolumeBeforeFrameStepping = m_wndToolBar.Volume;
    04241                 pBA->put_Volume(-10000);
    04242
    04243                 pFS->Step(1, NULL);
    04244         }
    04245         else if(S_OK == pMS->IsFormatSupported(&TIME_FORMAT_FRAME))
    04246         {
    04247                 if(GetMediaState() != State_Paused)
    04248                         SendMessage(WM_COMMAND, ID_PLAY_PAUSE);
    04249
    04250                 pMS->SetTimeFormat(&TIME_FORMAT_FRAME);
    04251                 pMS->GetCurrentPosition(&rt);
    04252                 if(nID == ID_PLAY_FRAMESTEP) rt++;
    04253                 else if(nID == ID_PLAY_FRAMESTEPCANCEL) rt--;
    04254                 pMS->SetPositions(&rt, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning);
    04255                 pMS->SetTimeFormat(&TIME_FORMAT_MEDIA_TIME);
    04256         }
    04257 }
    04258
    04259 void CMainFrame::OnUpdatePlayFramestep(CCmdUI* pCmdUI)
    04260 {
    04261         bool fEnable = false;
    04262
    04263         if(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly
    04264         && (m_iPlaybackMode != PM_DVD || m_iDVDDomain == DVD_DOMAIN_Title)
    04265         && m_iPlaybackMode != PM_CAPTURE
    04266         && !m_fLiveWM)
    04267         {
    04268                 REFTIME AvgTimePerFrame = 0;
    04269         if(S_OK == pMS->IsFormatSupported(&TIME_FORMAT_FRAME)
    04270                 || pCmdUI->m_nID == ID_PLAY_FRAMESTEP && pFS && pFS->CanStep(0, NULL) == S_OK
    04271                 || m_fQuicktimeGraph && pFS)
    04272                 {
    04273                         fEnable = true;
    04274                 }
    04275         }
    04276
    04277         pCmdUI->Enable(fEnable);
    04278 }
    04279
    04280 void CMainFrame::OnPlaySeek(UINT nID)
    04281 {
    04282         AppSettings& s = AfxGetAppSettings();
    04283
    04284         REFERENCE_TIME dt =
    04285                 nID == ID_PLAY_SEEKBACKWARDSMALL ? -10000i64*s.nJumpDistS :
    04286                 nID == ID_PLAY_SEEKFORWARDSMALL ? +10000i64*s.nJumpDistS :
    04287                 nID == ID_PLAY_SEEKBACKWARDMED ? -10000i64*s.nJumpDistM :
    04288                 nID == ID_PLAY_SEEKFORWARDMED ? +10000i64*s.nJumpDistM :
    04289                 nID == ID_PLAY_SEEKBACKWARDLARGE ? -10000i64*s.nJumpDistL :
    04290                 nID == ID_PLAY_SEEKFORWARDLARGE ? +10000i64*s.nJumpDistL :
    04291                 0;
    04292
    04293         if(!dt) return;
    04294
    04295         // HACK: the custom graph should support frame based seeking instead
    04296         if(m_fShockwaveGraph) dt /= 10000i64*100;
    04297
    04298         SeekTo(m_wndSeekBar.GetPos() + dt);
    04299 }
    04300
    04301 static int rangebsearch(REFERENCE_TIME val, CArray<REFERENCE_TIME>& rta)
    04302 {
    04303         int i = 0, j = rta.GetSize() - 1, ret = -1;
    04304
    04305         if(j >= 0 && val >= rta[j]) return(j);
    04306
    04307         while(i < j)
    04308         {
    04309                 int mid = (i + j) >> 1;
    04310                 REFERENCE_TIME midt = rta[mid];
    04311                 if(val == midt) {ret = mid; break;}
    04312                 else if(val < midt) {ret = -1; if(j == mid) mid--; j = mid;}
    04313                 else if(val > midt) {ret = mid; if(i == mid) mid++; i = mid;}
    04314         }
    04315
    04316         return(ret);
    04317 }
    04318
    04319 void CMainFrame::OnPlaySeekKey(UINT nID)
    04320 {
    04321         if(m_kfs.GetCount() > 0)
    04322         {
    04323                 HRESULT hr;
    04324
    04325                 if(GetMediaState() == State_Stopped)
    04326                         SendMessage(WM_COMMAND, ID_PLAY_PAUSE);
    04327
    04328                 REFERENCE_TIME rtCurrent, rtDur;
    04329                 hr = pMS->GetCurrentPosition(&rtCurrent);
    04330                 hr = pMS->GetDuration(&rtDur);
    04331
    04332                 int dec = 1;
    04333                 int i = rangebsearch(rtCurrent, m_kfs);
    04334                 if(i > 0) dec = (UINT)max(min(rtCurrent - m_kfs[i-1], 10000000), 0);
    04335
    04336                 rtCurrent =
    04337                         nID == ID_PLAY_SEEKKEYBACKWARD ? max(rtCurrent - dec, 0) :
    04338                         nID == ID_PLAY_SEEKKEYFORWARD ? rtCurrent : 0;
    04339
    04340                 i = rangebsearch(rtCurrent, m_kfs);
    04341
    04342                 if(nID == ID_PLAY_SEEKKEYBACKWARD)
    04343                         rtCurrent = m_kfs[max(i, 0)];
    04344                 else if(nID == ID_PLAY_SEEKKEYFORWARD && i < m_kfs.GetCount()-1)
    04345                         rtCurrent = m_kfs[i+1];
    04346                 else
    04347                         return;
    04348
    04349                 hr = pMS->SetPositions(
    04350                         &rtCurrent, AM_SEEKING_AbsolutePositioning|AM_SEEKING_SeekToKeyFrame,
    04351                         NULL, AM_SEEKING_NoPositioning);
    04352         }
    04353 }
    04354
    04355 void CMainFrame::OnUpdatePlaySeek(CCmdUI* pCmdUI)
    04356 {
    04357         bool fEnable = false;
    04358
    04359         OAFilterState fs = GetMediaState();
    04360
    04361         if(m_iMediaLoadState == MLS_LOADED && (fs == State_Paused || fs == State_Running))
    04362         {
    04363                 fEnable = true;
    04364                 if(m_iPlaybackMode == PM_DVD && (m_iDVDDomain != DVD_DOMAIN_Title || fs != State_Running)) fEnable = false;
    04365                 else if(m_iPlaybackMode == PM_CAPTURE) fEnable = false;
    04366         }
    04367
    04368         pCmdUI->Enable(fEnable);
    04369 }
    04370
    04371 void CMainFrame::OnPlayGoto()
    04372 {
    04373         if(m_iMediaLoadState != MLS_LOADED)
    04374                 return;
    04375
    04376         REFTIME atpf = 0;
    04377         if(FAILED(pBV->get_AvgTimePerFrame(&atpf)) || atpf < 0)
    04378         {
    04379                 atpf = 0;
    04380
    04381                 BeginEnumFilters(pGB, pEF, pBF)
    04382                 {
    04383                         if(atpf > 0) break;
    04384
    04385                         BeginEnumPins(pBF, pEP, pPin)
    04386                         {
    04387                                 if(atpf > 0) break;
    04388
    04389                                 AM_MEDIA_TYPE mt;
    04390                                 pPin->ConnectionMediaType(&mt);
    04391
    04392                                 if(mt.majortype == MEDIATYPE_Video && mt.formattype == FORMAT_VideoInfo)
    04393                                 {
    04394                                         atpf = (REFTIME)((VIDEOINFOHEADER*)mt.pbFormat)->AvgTimePerFrame / 10000000i64;
    04395                                 }
    04396                                 else if(mt.majortype == MEDIATYPE_Video && mt.formattype == FORMAT_VideoInfo2)
    04397                                 {
    04398                                         atpf = (REFTIME)((VIDEOINFOHEADER2*)mt.pbFormat)->AvgTimePerFrame / 10000000i64;
    04399                                 }
    04400                         }
    04401                         EndEnumPins
    04402                 }
    04403                 EndEnumFilters
    04404         }
    04405
    04406         CGoToDlg dlg((int)(m_wndSeekBar.GetPos()/10000), atpf > 0 ? (float)(1.0/atpf) : 0);
    04407         if(IDOK != dlg.DoModal() || dlg.m_time < 0) return;
    04408
    04409         SeekTo(10000i64 * dlg.m_time);
    04410 }
    04411
    04412 void CMainFrame::OnUpdateGoto(CCmdUI* pCmdUI)
    04413 {
    04414         bool fEnable = false;
    04415
    04416         if(m_iMediaLoadState == MLS_LOADED)
    04417         {
    04418                 fEnable = true;
    04419                 if(m_iPlaybackMode == PM_DVD && m_iDVDDomain != DVD_DOMAIN_Title) fEnable = false;
    04420                 else if(m_iPlaybackMode == PM_CAPTURE) fEnable = false;
    04421         }
    04422
    04423         pCmdUI->Enable(fEnable);
    04424 }
    04425
    04426 void CMainFrame::OnPlayChangeRate(UINT nID)
    04427 {
    04428         if(m_iMediaLoadState != MLS_LOADED)
    04429                 return;
    04430
    04431         if(m_iPlaybackMode == PM_CAPTURE)
    04432         {
    04433                 if(GetMediaState() != State_Running)
    04434                         SendMessage(WM_COMMAND, ID_PLAY_PLAY);
    04435
    04436                 long lChannelMin = 0, lChannelMax = 0;
    04437                 pAMTuner->ChannelMinMax(&lChannelMin, &lChannelMax);
    04438                 long lChannel = 0, lVivSub = 0, lAudSub = 0;
    04439                 pAMTuner->get_Channel(&lChannel, &lVivSub, &lAudSub);
    04440
    04441                 long lFreqOrg = 0, lFreqNew = -1;
    04442                 pAMTuner->get_VideoFrequency(&lFreqOrg);
    04443
    04444 //              long lSignalStrength;
    04445                 do
    04446                 {
    04447                         if(nID == ID_PLAY_DECRATE) lChannel--;
    04448                         else if(nID == ID_PLAY_INCRATE) lChannel++;
    04449
    04450 //                      if(lChannel < lChannelMin) lChannel = lChannelMax;
    04451 //                      if(lChannel > lChannelMax) lChannel = lChannelMin;
    04452
    04453                         if(lChannel < lChannelMin || lChannel > lChannelMax)
    04454                                 break;
    04455
    04456                         if(FAILED(pAMTuner->put_Channel(lChannel, AMTUNER_SUBCHAN_DEFAULT, AMTUNER_SUBCHAN_DEFAULT)))
    04457                                 break;
    04458
    04459                         long flFoundSignal;
    04460                         pAMTuner->AutoTune(lChannel, &flFoundSignal);
    04461
    04462                         pAMTuner->get_VideoFrequency(&lFreqNew);
    04463
    04464                         int i = 0;
    04465                 }
    04466                 while(FALSE);
    04467 /*                      SUCCEEDED(pAMTuner->SignalPresent(&lSignalStrength))
    04468                         && (lSignalStrength != AMTUNER_SIGNALPRESENT || lFreqNew == lFreqOrg));*/
    04469
    04470         }
    04471         else
    04472         {
    04473                 int iNewSpeedLevel;
    04474
    04475                 if(nID == ID_PLAY_INCRATE) iNewSpeedLevel = m_iSpeedLevel+1;
    04476                 else if(nID == ID_PLAY_DECRATE) iNewSpeedLevel = m_iSpeedLevel-1;
    04477                 else return;
    04478
    04479                 HRESULT hr = E_FAIL;
    04480
    04481                 if(iNewSpeedLevel == -4)
    04482                 {
    04483                         if(GetMediaState() != State_Paused)
    04484                                 SendMessage(WM_COMMAND, ID_PLAY_PAUSE);
    04485
    04486                         if(GetMediaState() == State_Paused) hr = S_OK;
    04487                 }
    04488                 else
    04489                 {
    04490                         double dRate = pow(2.0, iNewSpeedLevel >= -3 ? iNewSpeedLevel : (-iNewSpeedLevel - 8));
    04491                         if(fabs(dRate - 1.0) < 0.01) dRate = 1.0;
    04492
    04493                         if(GetMediaState() != State_Running)
    04494                                 SendMessage(WM_COMMAND, ID_PLAY_PLAY);
    04495
    04496                         if(m_iPlaybackMode == PM_FILE)
    04497                         {
    04498                                 hr = pMS->SetRate(dRate);
    04499                         }
    04500                         else if(m_iPlaybackMode == PM_DVD)
    04501                         {
    04502                                 if(iNewSpeedLevel >= -3)
    04503                                         hr = pDVDC->PlayForwards(dRate, DVD_CMD_FLAG_Block, NULL);
    04504                                 else
    04505                                         hr = pDVDC->PlayBackwards(dRate, DVD_CMD_FLAG_Block, NULL);
    04506                         }
    04507                 }
    04508
    04509                 if(SUCCEEDED(hr))
    04510                         m_iSpeedLevel = iNewSpeedLevel;
    04511         }
    04512 }
    04513
    04514 void CMainFrame::OnUpdatePlayChangeRate(CCmdUI* pCmdUI)
    04515 {
    04516         bool fEnable = false;
    04517
    04518         if(m_iMediaLoadState == MLS_LOADED)
    04519         {
    04520                 bool fInc = pCmdUI->m_nID == ID_PLAY_INCRATE;
    04521
    04522                 fEnable = true;
    04523                 if(fInc && m_iSpeedLevel >= 3) fEnable = false;
    04524                 else if(!fInc && m_iPlaybackMode == PM_FILE && m_iSpeedLevel <= -4) fEnable = false;
    04525                 else if(!fInc && m_iPlaybackMode == PM_DVD && m_iSpeedLevel <= -11) fEnable = false;
    04526                 else if(m_iPlaybackMode == PM_DVD && m_iDVDDomain != DVD_DOMAIN_Title) fEnable = false;
    04527                 else if(m_fRealMediaGraph || m_fShockwaveGraph) fEnable = false;
    04528                 else if(m_iPlaybackMode == PM_CAPTURE && (!m_wndCaptureBar.m_capdlg.IsTunerActive() || m_fCapturing)) fEnable = false;
    04529                 else if(m_fLiveWM) fEnable = false;
    04530         }
    04531
    04532         pCmdUI->Enable(fEnable);
    04533 }
    04534
    04535 void CMainFrame::OnPlayResetRate()
    04536 {
    04537         if(m_iMediaLoadState != MLS_LOADED)
    04538                 return;
    04539
    04540         HRESULT hr = E_FAIL;
    04541
    04542         if(GetMediaState() != State_Running)
    04543                 SendMessage(WM_COMMAND, ID_PLAY_PLAY);
    04544
    04545         if(m_iPlaybackMode == PM_FILE)
    04546         {
    04547                 hr = pMS->SetRate(1.0);
    04548         }
    04549         else if(m_iPlaybackMode == PM_DVD)
    04550         {
    04551                 hr = pDVDC->PlayForwards(1.0, DVD_CMD_FLAG_Block, NULL);
    04552         }
    04553
    04554         if(SUCCEEDED(hr))
    04555                 m_iSpeedLevel = 0;
    04556 }
    04557
    04558 void CMainFrame::OnUpdatePlayResetRate(CCmdUI* pCmdUI)
    04559 {
    04560         pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED);
    04561 }
    04562
    04563
    04564 void CMainFrame::OnPlayChangeAudDelay(UINT nID)
    04565 {
    04566         if(CComQIPtr<IAudioSwitcherFilter> pAS = FindFilter(__uuidof(CAudioSwitcherFilter), pGB))
    04567         {
    04568                 REFERENCE_TIME rtShift = pAS->GetAudioTimeShift();
    04569                 rtShift +=
    04570                         nID == ID_PLAY_INCAUDDELAY ? 100000 :
    04571                         nID == ID_PLAY_DECAUDDELAY ? -100000 :
    04572                         0;
    04573                 pAS->SetAudioTimeShift(rtShift);
    04574
    04575                 CString str;
    04576                 str.Format(_T("Audio Delay: %I64dms"), rtShift/10000);
    04577                 SendStatusMessage(str, 3000);
    04578         }
    04579 }
    04580
    04581 void CMainFrame::OnUpdatePlayChangeAudDelay(CCmdUI* pCmdUI)
    04582 {
    04583         pCmdUI->Enable(pGB && !!FindFilter(__uuidof(CAudioSwitcherFilter), pGB));
    04584 }
    04585
    04586 #include "ComPropertySheet.h"
    04587 #include ".\mainfrm.h"
    04588
    04589 void CMainFrame::OnPlayFilters(UINT nID)
    04590 {
    04591 //      ShowPPage(m_spparray[nID - ID_FILTERS_SUBITEM_START], m_hWnd);
    04592
    04593         CComPtr<ISpecifyPropertyPages> pSPP = m_spparray[nID - ID_FILTERS_SUBITEM_START];
    04594
    04595         CComPropertySheet ps(_T("Properties"), this);
    04596         ps.AddPages(pSPP);
    04597         ps.DoModal();
    04598
    04599         OpenSetupStatusBar();
    04600 }
    04601
    04602 void CMainFrame::OnUpdatePlayFilters(CCmdUI* pCmdUI)
    04603 {
    04604         pCmdUI->Enable(!m_fCapturing);
    04605 }
    04606
    04607 void CMainFrame::OnPlayShaders(UINT nID)
    04608 {
    04609         if(nID == ID_SHADERS_START)
    04610         {
    04611                 CShaderEditorDlg(m_shaderlabel, m_pCAP, this).DoModal();
    04612         }
    04613         else if(nID == ID_SHADERS_START+1)
    04614         {
    04615                 m_pCAP->SetPixelShader(NULL, NULL);
    04616                 m_shaderlabel.Empty();
    04617         }
    04618         else if(nID >= ID_SHADERS_START+2)
    04619         {
    04620                 nID -= ID_SHADERS_START+2;
    04621
    04622                 CString str;
    04623                 str.Format(_T("%d"), nID);
    04624
    04625                 CList<CString> sl;
    04626                 Explode(AfxGetApp()->GetProfileString(_T("Shaders"), str), sl, '|', 3);
    04627                 if(sl.GetCount() != 3) {AfxMessageBox(_T("Invalid shader data"), S_OK); return;}
    04628
    04629                 CString label = sl.RemoveHead();
    04630                 CStringA target = CStringA(sl.RemoveHead());
    04631                 CStringA srcdata = CStringA(sl.RemoveHead());
    04632
    04633                 srcdata.Replace("\\n", "\n");
    04634                 srcdata.Replace("\\t", "\t");
    04635
    04636                 HRESULT hr = m_pCAP->SetPixelShader(srcdata, target);
    04637                 if(FAILED(hr)) AfxMessageBox(_T("Could not load shader."), MB_OK);
    04638                 else {SendStatusMessage(_T("Shader: ") + label, 3000); m_shaderlabel = label;}
    04639         }
    04640 }
    04641
    04642 void CMainFrame::OnUpdatePlayShaders(CCmdUI* pCmdUI)
    04643 {
    04644         if(pCmdUI->m_nID > ID_SHADERS_START)
    04645         {
    04646                 pCmdUI->Enable(!!m_pCAP);
    04647
    04648                 if(pCmdUI->m_nID == ID_SHADERS_START+1)
    04649                 {
    04650                         pCmdUI->SetRadio(m_shaderlabel.IsEmpty());
    04651                 }
    04652                 else
    04653                 {
    04654                         CString str;
    04655                         m_shaders.GetMenuString(pCmdUI->m_nID, str, MF_BYCOMMAND);
    04656                         pCmdUI->SetRadio(str == m_shaderlabel);
    04657                 }
    04658         }
    04659 }
    04660
    04661 void CMainFrame::OnPlayAudio(UINT nID)
    04662 {
    04663         int i = (int)nID - (1 + ID_AUDIO_SUBITEM_START);
    04664
    04665         CComQIPtr<IAMStreamSelect> pSS = FindFilter(__uuidof(CAudioSwitcherFilter), pGB);
    04666         if(!pSS) pSS = FindFilter(L"{D3CD7858-971A-4838-ACEC-40CA5D529DC8}", pGB);
    04667
    04668         if(i == -1)
    04669         {
    04670                 ShowOptions(CPPageAudioSwitcher::IDD);
    04671         }
    04672         else if(i >= 0 && pSS)
    04673         {
    04674                 pSS->Enable(i, AMSTREAMSELECTENABLE_ENABLE);
    04675         }
    04676 }
    04677
    04678 void CMainFrame::OnUpdatePlayAudio(CCmdUI* pCmdUI)
    04679 {
    04680         UINT nID = pCmdUI->m_nID;
    04681         int i = (int)nID - (1 + ID_AUDIO_SUBITEM_START);
    04682
    04683         CComQIPtr<IAMStreamSelect> pSS = FindFilter(__uuidof(CAudioSwitcherFilter), pGB);
    04684         if(!pSS) pSS = FindFilter(L"{D3CD7858-971A-4838-ACEC-40CA5D529DC8}", pGB);
    04685
    04686         /*if(i == -1)
    04687         {
    04688                 // TODO****
    04689         }
    04690         else*/ if(i >= 0 && pSS)
    04691         {
    04692                 DWORD flags = 0;
    04693
    04694                 if(SUCCEEDED(pSS->Info(i, NULL, &flags, NULL, NULL, NULL, NULL, NULL)))
    04695                 {
    04696                         if(flags&AMSTREAMSELECTINFO_EXCLUSIVE) pCmdUI->SetRadio(TRUE);
    04697                         else if(flags&AMSTREAMSELECTINFO_ENABLED) pCmdUI->SetCheck(TRUE);
    04698                         else pCmdUI->SetCheck(FALSE);
    04699                 }
    04700                 else
    04701                 {
    04702                         pCmdUI->Enable(FALSE);
    04703                 }
    04704         }
    04705 }
    04706
    04707 void CMainFrame::OnPlaySubtitles(UINT nID)
    04708 {
    04709         int i = (int)nID - (4 + ID_SUBTITLES_SUBITEM_START);
    04710
    04711         if(i == -4)
    04712         {
    04713                 ShowOptions(CPPageSubtitles::IDD);
    04714         }
    04715         else if(i == -3)
    04716         {
    04717                 int i = m_iSubtitleSel;
    04718
    04719                 POSITION pos = m_pSubStreams.GetHeadPosition();
    04720                 while(pos && i >= 0)
    04721                 {
    04722                         CComPtr<ISubStream> pSubStream = m_pSubStreams.GetNext(pos);
    04723
    04724                         if(i < pSubStream->GetStreamCount())
    04725                         {
    04726                                 CLSID clsid;
    04727                                 if(FAILED(pSubStream->GetClassID(&clsid)))
    04728                                         continue;
    04729
    04730                                 if(clsid == __uuidof(CRenderedTextSubtitle))
    04731                                 {
    04732                                         CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)pSubStream;
    04733
    04734                                         CAutoPtrArray<CPPageSubStyle> pages;
    04735                                         CArray<STSStyle*> styles;
    04736
    04737                                         POSITION pos = pRTS->m_styles.GetStartPosition();
    04738                                         for(int i = 0; pos; i++)
    04739                                         {
    04740                                                 CString key;
    04741                                                 void* val;
    04742                                                 pRTS->m_styles.GetNextAssoc(pos, key, val);
    04743
    04744                                                 CAutoPtr<CPPageSubStyle> page(new CPPageSubStyle());
    04745                                                 page->InitStyle(key, *(STSStyle*)val);
    04746                                                 pages.Add(page);
    04747                                                 styles.Add((STSStyle*)val);
    04748                                         }
    04749
    04750                                         CPropertySheet dlg(_T("Styles..."), this);
    04751                                         for(int i = 0; i < (int)pages.GetCount(); i++)
    04752                                                 dlg.AddPage(pages[i]);
    04753
    04754                                         if(dlg.DoModal() == IDOK)
    04755                                         {
    04756                                                 for(int j = 0; j < (int)pages.GetCount(); j++)
    04757                                                         pages[j]->GetStyle(*styles[j]);
    04758                                                 UpdateSubtitle(false);
    04759                                         }
    04760
    04761                                         return;
    04762                                 }
    04763                         }
    04764
    04765                         i -= pSubStream->GetStreamCount();
    04766                 }
    04767         }
    04768         else if(i == -2)
    04769         {
    04770                 ReloadSubtitle();
    04771         }
    04772         else if(i == -1)
    04773         {
    04774                 m_iSubtitleSel ^= (1<<31);
    04775                 UpdateSubtitle();
    04776         }
    04777         else if(i >= 0)
    04778         {
    04779                 m_iSubtitleSel = i;
    04780                 UpdateSubtitle();
    04781         }
    04782 }
    04783
    04784 void CMainFrame::OnUpdatePlaySubtitles(CCmdUI* pCmdUI)
    04785 {
    04786         UINT nID = pCmdUI->m_nID;
    04787         int i = (int)nID - (4 + ID_SUBTITLES_SUBITEM_START);
    04788
    04789         pCmdUI->Enable(m_pCAP && !m_fAudioOnly);
    04790
    04791         if(i == -3)
    04792         {
    04793                 pCmdUI->Enable(FALSE);
    04794
    04795                 int i = m_iSubtitleSel;
    04796
    04797                 POSITION pos = m_pSubStreams.GetHeadPosition();
    04798                 while(pos && i >= 0)
    04799                 {
    04800                         CComPtr<ISubStream> pSubStream = m_pSubStreams.GetNext(pos);
    04801
    04802                         if(i < pSubStream->GetStreamCount())
    04803                         {
    04804                                 CLSID clsid;
    04805                                 if(FAILED(pSubStream->GetClassID(&clsid)))
    04806                                         continue;
    04807
    04808                                 if(clsid == __uuidof(CRenderedTextSubtitle))
    04809                                 {
    04810                                         pCmdUI->Enable(TRUE);
    04811                                         break;
    04812                                 }
    04813                         }
    04814
    04815                         i -= pSubStream->GetStreamCount();
    04816                 }
    04817         }
    04818         else if(i == -1)
    04819         {
    04820                 pCmdUI->SetCheck(m_iSubtitleSel >= 0);
    04821         }
    04822         else if(i >= 0)
    04823         {
    04824                 pCmdUI->SetRadio(i == abs(m_iSubtitleSel));
    04825         }
    04826 }
    04827
    04828 void CMainFrame::OnPlayLanguage(UINT nID)
    04829 {
    04830         nID -= ID_FILTERSTREAMS_SUBITEM_START;
    04831         CComPtr<IAMStreamSelect> pAMSS = m_ssarray[nID];
    04832         UINT i = nID;
    04833         while(i > 0 && pAMSS == m_ssarray[i-1]) i--;
    04834         if(FAILED(pAMSS->Enable(nID-i, AMSTREAMSELECTENABLE_ENABLE)))
    04835                 MessageBeep(-1);
    04836
    04837         OpenSetupStatusBar();
    04838 }
    04839
    04840 void CMainFrame::OnUpdatePlayLanguage(CCmdUI* pCmdUI)
    04841 {
    04842         UINT nID = pCmdUI->m_nID;
    04843         nID -= ID_FILTERSTREAMS_SUBITEM_START;
    04844         CComPtr<IAMStreamSelect> pAMSS = m_ssarray[nID];
    04845         UINT i = nID;
    04846         while(i > 0 && pAMSS == m_ssarray[i-1]) i--;
    04847         DWORD flags = 0;
    04848         pAMSS->Info(nID-i, NULL, &flags, NULL, NULL, NULL, NULL, NULL);
    04849         if(flags&AMSTREAMSELECTINFO_EXCLUSIVE) pCmdUI->SetRadio(TRUE);
    04850         else if(flags&AMSTREAMSELECTINFO_ENABLED) pCmdUI->SetCheck(TRUE);
    04851         else pCmdUI->SetCheck(FALSE);
    04852 }
    04853
    04854 void CMainFrame::OnPlayVolume(UINT nID)
    04855 {
    04856         if(m_iMediaLoadState == MLS_LOADED)
    04857                 pBA->put_Volume(m_wndToolBar.Volume);
    04858 }
    04859
    04860 void CMainFrame::OnAfterplayback(UINT nID)
    04861 {
    04862         AppSettings& s = AfxGetAppSettings();
    04863
    04864         s.nCLSwitches &= ~CLSW_AFTERPLAYBACK_MASK;
    04865
    04866         switch(nID)
    04867         {
    04868         case ID_AFTERPLAYBACK_CLOSE: s.nCLSwitches |= CLSW_CLOSE; break;
    04869         case ID_AFTERPLAYBACK_STANDBY: s.nCLSwitches |= CLSW_STANDBY; break;
    04870         case ID_AFTERPLAYBACK_HIBERNATE: s.nCLSwitches |= CLSW_HIBERNATE; break;
    04871         case ID_AFTERPLAYBACK_SHUTDOWN: s.nCLSwitches |= CLSW_SHUTDOWN; break;
    04872         case ID_AFTERPLAYBACK_LOGOFF: s.nCLSwitches |= CLSW_LOGOFF; break;
    04873         }
    04874 }
    04875
    04876 void CMainFrame::OnUpdateAfterplayback(CCmdUI* pCmdUI)
    04877 {
    04878         AppSettings& s = AfxGetAppSettings();
    04879
    04880         bool fChecked = false;
    04881
    04882         switch(pCmdUI->m_nID)
    04883         {
    04884         case ID_AFTERPLAYBACK_CLOSE: fChecked = !!(s.nCLSwitches & CLSW_CLOSE); break;
    04885         case ID_AFTERPLAYBACK_STANDBY: fChecked = !!(s.nCLSwitches & CLSW_STANDBY); break;
    04886         case ID_AFTERPLAYBACK_HIBERNATE: fChecked = !!(s.nCLSwitches & CLSW_HIBERNATE); break;
    04887         case ID_AFTERPLAYBACK_SHUTDOWN: fChecked = !!(s.nCLSwitches & CLSW_SHUTDOWN); break;
    04888         case ID_AFTERPLAYBACK_LOGOFF: fChecked = !!(s.nCLSwitches & CLSW_LOGOFF); break;
    04889         case ID_AFTERPLAYBACK_DONOTHING: fChecked = !(s.nCLSwitches & CLSW_AFTERPLAYBACK_MASK); break;
    04890         }
    04891
    04892         pCmdUI->SetRadio(fChecked);
    04893 }
    04894
    04895 // navigate
    04896
    04897 void CMainFrame::OnNavigateSkip(UINT nID)
    04898 {
    04899         if(m_iPlaybackMode == PM_FILE || m_iPlaybackMode == PM_CAPTURE)
    04900         {
    04901                 if(m_iPlaybackMode == PM_FILE) SetupChapters();
    04902
    04903                 if(DWORD nChapters = m_pCB->ChapGetCount())
    04904                 {
    04905                         REFERENCE_TIME rtCur;
    04906                         pMS->GetCurrentPosition(&rtCur);
    04907
    04908                         REFERENCE_TIME rt = rtCur;
    04909                         CComBSTR name;
    04910                         long i;
    04911
    04912                         if(nID == ID_NAVIGATE_SKIPBACK)
    04913                         {
    04914                                 rt -= 30000000;
    04915                                 i = m_pCB->ChapLookup(&rt, &name);
    04916                         }
    04917                         else if(nID == ID_NAVIGATE_SKIPFORWARD)
    04918                         {
    04919                                 i = m_pCB->ChapLookup(&rt, &name) + 1;
    04920                                 name.Empty();
    04921                                 if(i < nChapters) m_pCB->ChapGet(i, &rt, &name);
    04922                         }
    04923
    04924                         if(i >= 0 && i < nChapters)
    04925                         {
    04926                                 SeekTo(rt);
    04927                                 SendStatusMessage(_T("Chapter: ") + CString(name), 3000);
    04928                                 return;
    04929                         }
    04930                 }
    04931
    04932                 if(nID == ID_NAVIGATE_SKIPBACK)
    04933                 {
    04934                         SendMessage(WM_COMMAND, ID_NAVIGATE_SKIPBACKPLITEM);
    04935                 }
    04936                 else if(nID == ID_NAVIGATE_SKIPFORWARD)
    04937                 {
    04938                         SendMessage(WM_COMMAND, ID_NAVIGATE_SKIPFORWARDPLITEM);
    04939                 }
    04940         }
    04941         else if(m_iPlaybackMode == PM_DVD)
    04942         {
    04943                 m_iSpeedLevel = 0;
    04944
    04945                 if(GetMediaState() != State_Running)
    04946                         SendMessage(WM_COMMAND, ID_PLAY_PLAY);
    04947
    04948                 ULONG ulNumOfVolumes, ulVolume;
    04949                 DVD_DISC_SIDE Side;
    04950                 ULONG ulNumOfTitles = 0;
    04951                 pDVDI->GetDVDVolumeInfo(&ulNumOfVolumes, &ulVolume, &Side, &ulNumOfTitles);
    04952
    04953                 DVD_PLAYBACK_LOCATION2 Location;
    04954                 pDVDI->GetCurrentLocation(&Location);
    04955
    04956                 ULONG ulNumOfChapters = 0;
    04957                 pDVDI->GetNumberOfChapters(Location.TitleNum, &ulNumOfChapters);
    04958
    04959                 if(nID == ID_NAVIGATE_SKIPBACK)
    04960                 {
    04961                         if(Location.ChapterNum == 1 && Location.TitleNum > 1)
    04962                         {
    04963                                 pDVDI->GetNumberOfChapters(Location.TitleNum-1, &ulNumOfChapters);
    04964                                 pDVDC->PlayChapterInTitle(Location.TitleNum-1, ulNumOfChapters, DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
    04965                         }
    04966                         else
    04967                         {
    04968                                 pDVDC->PlayPrevChapter(DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
    04969                         }
    04970                 }
    04971                 else if(nID == ID_NAVIGATE_SKIPFORWARD)
    04972                 {
    04973                         if(Location.ChapterNum == ulNumOfChapters && Location.TitleNum < ulNumOfTitles)
    04974                         {
    04975                                 pDVDC->PlayChapterInTitle(Location.TitleNum+1, 1, DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
    04976                         }
    04977                         else
    04978                         {
    04979                                 pDVDC->PlayNextChapter(DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
    04980                         }
    04981                 }
    04982 /*
    04983         if(nID == ID_NAVIGATE_SKIPBACK)
    04984                         pDVDC->PlayPrevChapter(DVD_CMD_FLAG_Block, NULL);
    04985                 else if(nID == ID_NAVIGATE_SKIPFORWARD)
    04986                         pDVDC->PlayNextChapter(DVD_CMD_FLAG_Block, NULL);
    04987 */
    04988         }
    04989 }
    04990
    04991 void CMainFrame::OnUpdateNavigateSkip(CCmdUI* pCmdUI)
    04992 {
    04993         // moved to the timer callback function, that runs less frequent
    04994 //      if(m_iPlaybackMode == PM_FILE) SetupChapters();
    04995
    04996         pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED
    04997                 && ((m_iPlaybackMode == PM_DVD
    04998                                 && m_iDVDDomain != DVD_DOMAIN_VideoManagerMenu
    04999                                 && m_iDVDDomain != DVD_DOMAIN_VideoTitleSetMenu)
    05000                         || (m_iPlaybackMode == PM_FILE && (m_wndPlaylistBar.GetCount() > 1/*0*/ || m_pCB->ChapGetCount() > 1))
    05001                         || (m_iPlaybackMode == PM_CAPTURE && !m_fCapturing))); // TODO
    05002 }
    05003
    05004 void CMainFrame::OnNavigateSkipPlaylistItem(UINT nID)
    05005 {
    05006         if(m_iPlaybackMode == PM_FILE || m_iPlaybackMode == PM_CAPTURE)
    05007         {
    05008                 if(m_wndPlaylistBar.GetCount() == 1)
    05009                 {
    05010                         SendMessage(WM_COMMAND, ID_PLAY_STOP); // do not remove this, unless you want a circular call with OnPlayPlay()
    05011                         SendMessage(WM_COMMAND, ID_PLAY_PLAY);
    05012                 }
    05013                 else
    05014                 {
    05015                         if(nID == ID_NAVIGATE_SKIPBACKPLITEM)
    05016                         {
    05017                                 m_wndPlaylistBar.SetPrev();
    05018                         }
    05019                         else if(nID == ID_NAVIGATE_SKIPFORWARDPLITEM)
    05020                         {
    05021                                 m_wndPlaylistBar.SetNext();
    05022                         }
    05023
    05024                         OpenCurPlaylistItem();
    05025                 }
    05026         }
    05027 }
    05028
    05029 void CMainFrame::OnUpdateNavigateSkipPlaylistItem(CCmdUI* pCmdUI)
    05030 {
    05031         pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED
    05032                 && ((m_iPlaybackMode == PM_FILE || m_iPlaybackMode == PM_CAPTURE && !m_fCapturing) && m_wndPlaylistBar.GetCount() > 1/*0*/));
    05033 }
    05034
    05035 void CMainFrame::OnNavigateMenu(UINT nID)
    05036 {
    05037         nID -= ID_NAVIGATE_TITLEMENU;
    05038
    05039         if(m_iMediaLoadState != MLS_LOADED || m_iPlaybackMode != PM_DVD)
    05040                 return;
    05041
    05042         m_iSpeedLevel = 0;
    05043
    05044         if(GetMediaState() != State_Running)
    05045                 SendMessage(WM_COMMAND, ID_PLAY_PLAY);
    05046
    05047         pDVDC->ShowMenu((DVD_MENU_ID)(nID+2), DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
    05048 }
    05049
    05050 void CMainFrame::OnUpdateNavigateMenu(CCmdUI* pCmdUI)
    05051 {
    05052         UINT nID = pCmdUI->m_nID - ID_NAVIGATE_TITLEMENU;
    05053         ULONG ulUOPs;
    05054
    05055         if(m_iMediaLoadState != MLS_LOADED || m_iPlaybackMode != PM_DVD
    05056                 || FAILED(pDVDI->GetCurrentUOPS(&ulUOPs)))
    05057         {
    05058                 pCmdUI->Enable(FALSE);
    05059                 return;
    05060         }
    05061
    05062         pCmdUI->Enable(!(ulUOPs & (UOP_FLAG_ShowMenu_Title << nID)));
    05063 }
    05064
    05065 void CMainFrame::OnNavigateAudio(UINT nID)
    05066 {
    05067         nID -= ID_NAVIGATE_AUDIO_SUBITEM_START;
    05068
    05069         if(m_iPlaybackMode == PM_FILE)
    05070         {
    05071                 OnNavStreamSelectSubMenu(nID, 1);
    05072         }
    05073         else if(m_iPlaybackMode == PM_DVD)
    05074         {
    05075                 pDVDC->SelectAudioStream(nID, DVD_CMD_FLAG_Block, NULL);
    05076         }
    05077 }
    05078
    05079 void CMainFrame::OnNavigateSubpic(UINT nID)
    05080 {
    05081         if(m_iPlaybackMode == PM_FILE)
    05082         {
    05083                 OnNavStreamSelectSubMenu(nID - ID_NAVIGATE_SUBP_SUBITEM_START, 2);
    05084         }
    05085         else if(m_iPlaybackMode == PM_DVD)
    05086         {
    05087                 int i = (int)nID - (1 + ID_NAVIGATE_SUBP_SUBITEM_START);
    05088
    05089                 if(i == -1)
    05090                 {
    05091                         ULONG ulStreamsAvailable, ulCurrentStream;
    05092                         BOOL bIsDisabled;
    05093                         if(SUCCEEDED(pDVDI->GetCurrentSubpicture(&ulStreamsAvailable, &ulCurrentStream, &bIsDisabled)))
    05094                                 pDVDC->SetSubpictureState(bIsDisabled, DVD_CMD_FLAG_Block, NULL);
    05095                 }
    05096                 else
    05097                 {
    05098                         pDVDC->SelectSubpictureStream(i, DVD_CMD_FLAG_Block, NULL);
    05099                         pDVDC->SetSubpictureState(TRUE, DVD_CMD_FLAG_Block, NULL);
    05100                 }
    05101         }
    05102 }
    05103
    05104 void CMainFrame::OnNavigateAngle(UINT nID)
    05105 {
    05106         nID -= ID_NAVIGATE_ANGLE_SUBITEM_START;
    05107
    05108         if(m_iPlaybackMode == PM_FILE)
    05109         {
    05110                 OnNavStreamSelectSubMenu(nID, 0);
    05111         }
    05112         else if(m_iPlaybackMode == PM_DVD)
    05113         {
    05114                 pDVDC->SelectAngle(nID, DVD_CMD_FLAG_Block, NULL);
    05115         }
    05116 }
    05117
    05118 void CMainFrame::OnNavigateChapters(UINT nID)
    05119 {
    05120         nID -= ID_NAVIGATE_CHAP_SUBITEM_START;
    05121
    05122         if(m_iPlaybackMode == PM_FILE)
    05123         {
    05124                 if((int)nID >= 0 && nID < m_pCB->ChapGetCount())
    05125                 {
    05126                         REFERENCE_TIME rt;
    05127                         CComBSTR name;
    05128                         if(SUCCEEDED(m_pCB->ChapGet(nID, &rt, &name)))
    05129                         {
    05130                                 SeekTo(rt);
    05131                                 SendStatusMessage(_T("Chapter: ") + CString(name), 3000);
    05132                         }
    05133                         return;
    05134                 }
    05135
    05136                 nID -= m_pCB->ChapGetCount();
    05137
    05138                 if((int)nID >= 0 && (int)nID < m_wndPlaylistBar.GetCount()
    05139                 && m_wndPlaylistBar.GetSelIdx() != (int)nID)
    05140                 {
    05141                         m_wndPlaylistBar.SetSelIdx(nID);
    05142                         OpenCurPlaylistItem();
    05143                 }
    05144         }
    05145         else if(m_iPlaybackMode == PM_DVD)
    05146         {
    05147                 ULONG ulNumOfVolumes, ulVolume;
    05148                 DVD_DISC_SIDE Side;
    05149                 ULONG ulNumOfTitles = 0;
    05150                 pDVDI->GetDVDVolumeInfo(&ulNumOfVolumes, &ulVolume, &Side, &ulNumOfTitles);
    05151
    05152                 DVD_PLAYBACK_LOCATION2 Location;
    05153                 pDVDI->GetCurrentLocation(&Location);
    05154
    05155                 ULONG ulNumOfChapters = 0;
    05156                 pDVDI->GetNumberOfChapters(Location.TitleNum, &ulNumOfChapters);
    05157
    05158                 nID++;
    05159
    05160                 if(nID > 0 && nID <= ulNumOfTitles)
    05161                 {
    05162                         pDVDC->PlayTitle(nID, DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL); // sometimes this does not do anything ...
    05163                         pDVDC->PlayChapterInTitle(nID, 1, DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL); // ... but this does!
    05164                         return;
    05165                 }
    05166
    05167                 nID -= ulNumOfTitles;
    05168
    05169                 if(nID > 0 && nID <= ulNumOfChapters)
    05170                 {
    05171                         pDVDC->PlayChapter(nID, DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
    05172                         return;
    05173                 }
    05174         }
    05175 }
    05176
    05177 void CMainFrame::OnNavigateMenuItem(UINT nID)
    05178 {
    05179         nID -= ID_NAVIGATE_MENU_LEFT;
    05180
    05181         if(m_iPlaybackMode == PM_DVD)
    05182         {
    05183                 switch(nID)
    05184                 {
    05185                 case 0: pDVDC->SelectRelativeButton(DVD_Relative_Left); break;
    05186                 case 1: pDVDC->SelectRelativeButton(DVD_Relative_Right); break;
    05187                 case 2: pDVDC->SelectRelativeButton(DVD_Relative_Upper); break;
    05188                 case 3: pDVDC->SelectRelativeButton(DVD_Relative_Lower); break;
    05189                 case 4: pDVDC->ActivateButton(); break;
    05190                 case 5: pDVDC->ReturnFromSubmenu(DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL); break;
    05191                 case 6: pDVDC->Resume(DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL); break;
    05192                 default: break;
    05193                 }
    05194         }
    05195 }
    05196
    05197 void CMainFrame::OnUpdateNavigateMenuItem(CCmdUI* pCmdUI)
    05198 {
    05199         UINT nID = pCmdUI->m_nID - ID_NAVIGATE_MENU_LEFT;
    05200         pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && m_iPlaybackMode == PM_DVD);
    05201 }
    05202
    05203 // favorites
    05204
    05205 class CDVDStateStream : public CUnknown, public IStream
    05206 {
    05207         STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv)
    05208         {
    05209                 return
    05210                         QI(IStream)
    05211                         CUnknown::NonDelegatingQueryInterface(riid, ppv);
    05212         }
    05213
    05214         __int64 m_pos;
    05215
    05216 public:
    05217         CDVDStateStream() : CUnknown(NAME("CDVDStateStream"), NULL) {m_pos = 0;}
    05218
    05219         DECLARE_IUNKNOWN;
    05220
    05221         CByteArray m_data;
    05222
    05223     // ISequentialStream
    05224         STDMETHODIMP Read(void* pv, ULONG cb, ULONG* pcbRead)
    05225         {
    05226                 __int64 cbRead = min(m_data.GetCount() - m_pos, (__int64)cb);
    05227                 cbRead = max(cbRead, 0);
    05228                 memcpy(pv, &m_data[(INT_PTR)m_pos], (int)cbRead);
    05229                 if(pcbRead) *pcbRead = (ULONG)cbRead;
    05230                 m_pos += cbRead;
    05231                 return S_OK;
    05232         }
    05233         STDMETHODIMP Write(const void* pv, ULONG cb, ULONG* pcbWritten)
    05234         {
    05235                 BYTE* p = (BYTE*)pv;
    05236                 ULONG cbWritten = -1;
    05237                 while(++cbWritten < cb)
    05238                         m_data.Add(*p++);
    05239                 if(pcbWritten) *pcbWritten = cbWritten;
    05240                 return S_OK;
    05241         }
    05242
    05243         // IStream
    05244         STDMETHODIMP Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition) {return E_NOTIMPL;}
    05245         STDMETHODIMP SetSize(ULARGE_INTEGER libNewSize) {return E_NOTIMPL;}
    05246         STDMETHODIMP CopyTo(IStream* pstm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten) {return E_NOTIMPL;}
    05247         STDMETHODIMP Commit(DWORD grfCommitFlags) {return E_NOTIMPL;}
    05248         STDMETHODIMP Revert() {return E_NOTIMPL;}
    05249         STDMETHODIMP LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {return E_NOTIMPL;}
    05250         STDMETHODIMP UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {return E_NOTIMPL;}
    05251         STDMETHODIMP Stat(STATSTG* pstatstg, DWORD grfStatFlag) {return E_NOTIMPL;}
    05252         STDMETHODIMP Clone(IStream** ppstm) {return E_NOTIMPL;}
    05253 };
    05254
    05255
    05256 void CMainFrame::OnFavoritesAdd()
    05257 {
    05258         AppSettings& s = AfxGetAppSettings();
    05259
    05260         if(m_iPlaybackMode == PM_FILE)
    05261         {
    05262                 CString fn =  m_wndPlaylistBar.GetCur();
    05263                 if(fn.IsEmpty()) return;
    05264
    05265                 CString desc = fn;
    05266                 desc.Replace('\\', '/');
    05267                 int i = desc.Find(_T("://")), j = desc.Find(_T("?")), k = desc.ReverseFind('/');
    05268                 if(i >= 0) desc = j >= 0 ? desc.Left(j) : desc;
    05269                 else if(k >= 0) desc = desc.Mid(k+1);
    05270
    05271                 CFavoriteAddDlg dlg(desc, fn);
    05272                 if(dlg.DoModal() != IDOK) return;
    05273
    05274                 CString str = dlg.m_name;
    05275                 str.Remove(';');
    05276
    05277                 CString pos(_T("0"));
    05278                 if(dlg.m_fRememberPos)
    05279                         pos.Format(_T("%I64d"), GetPos());
    05280
    05281                 str += ';';
    05282                 str += pos;
    05283
    05284                 CPlaylistItem pli;
    05285                 if(m_wndPlaylistBar.GetCur(pli))
    05286                 {
    05287                         POSITION pos = pli.m_fns.GetHeadPosition();
    05288                         while(pos) str += _T(";") + pli.m_fns.GetNext(pos);
    05289                 }
    05290
    05291                 s.AddFav(FAV_FILE, str);
    05292         }
    05293         else if(m_iPlaybackMode == PM_DVD)
    05294         {
    05295                 WCHAR path[MAX_PATH];
    05296                 ULONG len = 0;
    05297                 pDVDI->GetDVDDirectory(path, MAX_PATH, &len);
    05298                 CString fn = path;
    05299                 fn.TrimRight(_T("/\\"));
    05300
    05301                 DVD_PLAYBACK_LOCATION2 Location;
    05302                 pDVDI->GetCurrentLocation(&Location);
    05303                 CString desc;
    05304                 desc.Format(_T("%s - T%02d C%02d - %02d:%02d:%02d"), fn, Location.TitleNum, Location.ChapterNum,
    05305                         Location.TimeCode.bHours, Location.TimeCode.bMinutes, Location.TimeCode.bSeconds);
    05306
    05307                 CFavoriteAddDlg dlg(fn, desc);
    05308                 if(dlg.DoModal() != IDOK) return;
    05309
    05310                 CString str = dlg.m_name;
    05311                 str.Remove(';');
    05312
    05313                 CString pos(_T("0"));
    05314                 if(dlg.m_fRememberPos)
    05315                 {
    05316                         CDVDStateStream stream;
    05317                         stream.AddRef();
    05318
    05319                         CComPtr<IDvdState> pStateData;
    05320                         CComQIPtr<IPersistStream> pPersistStream;
    05321                         if(SUCCEEDED(pDVDI->GetState(&pStateData))
    05322                         && (pPersistStream = pStateData)
    05323                         && SUCCEEDED(OleSaveToStream(pPersistStream, (IStream*)&stream)))
    05324                         {
    05325                                 pos = BinToString(stream.m_data.GetData(), stream.m_data.GetCount());
    05326                         }
    05327                 }
    05328
    05329                 str += ';';
    05330                 str += pos;
    05331
    05332                 str += ';';
    05333                 str += fn;
    05334
    05335                 s.AddFav(FAV_DVD, str);
    05336         }
    05337         else if(m_iPlaybackMode == PM_CAPTURE)
    05338         {
    05339                 // TODO
    05340         }
    05341 }
    05342
    05343 void CMainFrame::OnUpdateFavoritesAdd(CCmdUI* pCmdUI)
    05344 {
    05345         pCmdUI->Enable(m_iPlaybackMode == PM_FILE || m_iPlaybackMode == PM_DVD);
    05346 }
    05347
    05348 void CMainFrame::OnFavoritesOrganize()
    05349 {
    05350         CFavoriteOrganizeDlg dlg;
    05351         dlg.DoModal();
    05352 }
    05353
    05354 void CMainFrame::OnUpdateFavoritesOrganize(CCmdUI* pCmdUI)
    05355 {
    05356         // TODO: Add your command update UI handler code here
    05357 }
    05358
    05359 void CMainFrame::OnFavoritesFile(UINT nID)
    05360 {
    05361         nID -= ID_FAVORITES_FILE_START;
    05362
    05363         CList<CString> sl;
    05364         AfxGetAppSettings().GetFav(FAV_FILE, sl);
    05365
    05366         if(POSITION pos = sl.FindIndex(nID))
    05367         {
    05368                 CList<CString> fns;
    05369                 REFERENCE_TIME rtStart = 0;
    05370
    05371                 int i = 0, j = 0;
    05372                 for(CString s1 = sl.GetAt(pos), s2 = s1.Tokenize(_T(";"), i);
    05373                         !s2.IsEmpty();
    05374                         s2 = s1.Tokenize(_T(";"), i), j++)
    05375                 {
    05376                         if(j == 0) ; // desc
    05377                         else if(j == 1) _stscanf(s2, _T("%I64d"), &rtStart); // pos
    05378                         else fns.AddTail(s2); // subs
    05379                 }
    05380
    05381                 m_wndPlaylistBar.Open(fns, false);
    05382                 OpenCurPlaylistItem(max(rtStart, 0));
    05383         }
    05384 }
    05385
    05386 void CMainFrame::OnUpdateFavoritesFile(CCmdUI* pCmdUI)
    05387 {
    05388         UINT nID = pCmdUI->m_nID - ID_FAVORITES_FILE_START;
    05389 }
    05390
    05391 void CMainFrame::OnFavoritesDVD(UINT nID)
    05392 {
    05393         nID -= ID_FAVORITES_DVD_START;
    05394
    05395         CList<CString> sl;
    05396         AfxGetAppSettings().GetFav(FAV_DVD, sl);
    05397
    05398         if(POSITION pos = sl.FindIndex(nID))
    05399         {
    05400                 CString fn;
    05401
    05402                 CDVDStateStream stream;
    05403                 stream.AddRef();
    05404
    05405                 int i = 0, j = 0;
    05406                 for(CString s1 = sl.GetAt(pos), s2 = s1.Tokenize(_T(";"), i);
    05407                         !s2.IsEmpty();
    05408                         s2 = s1.Tokenize(_T(";"), i), j++)
    05409                 {
    05410                         if(j == 0) ; // desc
    05411                         else if(j == 1 && s2 != _T("0")) // state
    05412                         {
    05413                                 StringToBin(s2, stream.m_data);
    05414                         }
    05415                         else if(j == 2) fn = s2; // path
    05416                 }
    05417
    05418                 SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
    05419
    05420                 CComPtr<IDvdState> pDvdState;
    05421                 HRESULT hr = OleLoadFromStream((IStream*)&stream, IID_IDvdState, (void**)&pDvdState);
    05422
    05423                 CAutoPtr<OpenDVDData> p(new OpenDVDData());
    05424                 if(p) {p->path = fn; p->pDvdState = pDvdState;}
    05425                 OpenMedia(p);
    05426         }
    05427 }
    05428
    05429 void CMainFrame::OnUpdateFavoritesDVD(CCmdUI* pCmdUI)
    05430 {
    05431         UINT nID = pCmdUI->m_nID - ID_FAVORITES_DVD_START;
    05432 }
    05433
    05434 void CMainFrame::OnFavoritesDevice(UINT nID)
    05435 {
    05436         nID -= ID_FAVORITES_DEVICE_START;
    05437 }
    05438
    05439 void CMainFrame::OnUpdateFavoritesDevice(CCmdUI* pCmdUI)
    05440 {
    05441         UINT nID = pCmdUI->m_nID - ID_FAVORITES_DEVICE_START;
    05442 }
    05443
    05444 // help
    05445
    05446 void CMainFrame::OnHelpHomepage()
    05447 {
    05448         ShellExecute(m_hWnd, _T("open"), _T("http://gabest.org/"), NULL, NULL, SW_SHOWDEFAULT);
    05449 }
    05450
    05451 void CMainFrame::OnHelpDocumentation()
    05452 {
    05453         ShellExecute(m_hWnd, _T("open"), _T("http://sourceforge.net/project/showfiles.php?group_id=82303&package_id=144472"), NULL, NULL, SW_SHOWDEFAULT);
    05454 }
    05455
    05456 void CMainFrame::OnHelpDonate()
    05457 {
    05458         const TCHAR URL[] = _T("http://order.kagi.com/?N4A");
    05459         if(CString(URL).Find(CString(_T("A4N")).MakeReverse()) >= 0)
    05460                 ShellExecute(m_hWnd, _T("open"), URL, NULL, NULL, SW_SHOWDEFAULT);
    05461 }
    05462
    05464
    05465
    05466 void CMainFrame::SetDefaultWindowRect()
    05467 {
    05468         AppSettings& s = AfxGetAppSettings();
    05469
    05470         {
    05471                 CRect r1, r2;
    05472                 GetClientRect(&r1);
    05473                 m_wndView.GetClientRect(&r2);
    05474
    05475                 CSize logosize = m_wndView.GetLogoSize();
    05476                 int _DEFCLIENTW = max(logosize.cx, DEFCLIENTW);
    05477                 int _DEFCLIENTH = max(logosize.cy, DEFCLIENTH);
    05478
    05479                 DWORD style = GetStyle();
    05480
    05481                 MENUBARINFO mbi;
    05482                 memset(&mbi, 0, sizeof(mbi));
    05483                 mbi.cbSize = sizeof(mbi);
    05484                 ::GetMenuBarInfo(m_hWnd, OBJID_MENU, 0, &mbi);
    05485
    05486                 int w = _DEFCLIENTW + GetSystemMetrics((style&WS_CAPTION)?SM_CXSIZEFRAME:SM_CXFIXEDFRAME)*2
    05487                         + r1.Width() - r2.Width();
    05488                 int h = _DEFCLIENTH + GetSystemMetrics((style&WS_CAPTION)?SM_CYSIZEFRAME:SM_CYFIXEDFRAME)*2
    05489                         + (mbi.rcBar.bottom - mbi.rcBar.top)
    05490                         + r1.Height() - r2.Height()
    05491                         + 1; // ???
    05492 //                      + 2; // ???
    05493                 if(style&WS_CAPTION) h += GetSystemMetrics(SM_CYCAPTION);
    05494
    05495                 if(s.HasFixedWindowSize())
    05496                 {
    05497                         w = s.fixedWindowSize.cx;
    05498                         h = s.fixedWindowSize.cy;
    05499                 }
    05500                 else if(s.fRememberWindowSize)
    05501                 {
    05502                         w = s.rcLastWindowPos.Width();
    05503                         h = s.rcLastWindowPos.Height();
    05504                 }
    05505
    05506                 MONITORINFO mi;
    05507                 mi.cbSize = sizeof(MONITORINFO);
    05508                 GetMonitorInfo(MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST), &mi);
    05509
    05510                 int x = (mi.rcWork.left+mi.rcWork.right-w)/2;
    05511                 int y = (mi.rcWork.top+mi.rcWork.bottom-h)/2;
    05512
    05513                 if(s.fRememberWindowPos)
    05514                 {
    05515                         CRect r = s.rcLastWindowPos;
    05516 //                      x = r.CenterPoint().x - w/2;
    05517 //                      y = r.CenterPoint().y - h/2;
    05518                         x = r.TopLeft().x;
    05519                         y = r.TopLeft().y;
    05520                 }
    05521
    05522                 UINT lastWindowType = s.lastWindowType;
    05523
    05524                 MoveWindow(x, y, w, h);
    05525
    05526                 if(s.fRememberWindowSize && s.fRememberWindowPos)
    05527                 {
    05528                         WINDOWPLACEMENT wp;
    05529                         memset(&wp, 0, sizeof(wp));
    05530                         wp.length = sizeof(WINDOWPLACEMENT);
    05531                         if(lastWindowType == SIZE_MAXIMIZED)
    05532                                 ShowWindow(SW_MAXIMIZE);
    05533                         else if(lastWindowType == SIZE_MINIMIZED)
    05534                                 ShowWindow(SW_MINIMIZE);
    05535                 }
    05536         }
    05537
    05538         if(s.fHideCaptionMenu)
    05539         {
    05540                 ModifyStyle(WS_CAPTION, 0, SWP_NOZORDER);
    05541                 ::SetMenu(m_hWnd, NULL);
    05542                 SetWindowPos(NULL, 0, 0, 0, 0, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER);
    05543         }
    05544 }
    05545
    05546 void CMainFrame::RestoreDefaultWindowRect()
    05547 {
    05548         AppSettings& s = AfxGetAppSettings();
    05549
    05550         WINDOWPLACEMENT wp;
    05551         GetWindowPlacement(&wp);
    05552         if(!m_fFullScreen && wp.showCmd != SW_SHOWMAXIMIZED && wp.showCmd != SW_SHOWMINIMIZED
    05553 //      && (GetExStyle()&WS_EX_APPWINDOW)
    05554         && !s.fRememberWindowSize)
    05555         {
    05556                 CRect r1, r2;
    05557                 GetClientRect(&r1);
    05558                 m_wndView.GetClientRect(&r2);
    05559
    05560                 CSize logosize = m_wndView.GetLogoSize();
    05561                 int _DEFCLIENTW = max(logosize.cx, DEFCLIENTW);
    05562                 int _DEFCLIENTH = max(logosize.cy, DEFCLIENTH);
    05563
    05564                 DWORD style = GetStyle();
    05565
    05566                 MENUBARINFO mbi;
    05567                 memset(&mbi, 0, sizeof(mbi));
    05568                 mbi.cbSize = sizeof(mbi);
    05569                 ::GetMenuBarInfo(m_hWnd, OBJID_MENU, 0, &mbi);
    05570
    05571                 int w = _DEFCLIENTW + GetSystemMetrics((style&WS_CAPTION)?SM_CXSIZEFRAME:SM_CXFIXEDFRAME)*2
    05572                         + r1.Width() - r2.Width();
    05573                 int h = _DEFCLIENTH + GetSystemMetrics((style&WS_CAPTION)?SM_CYSIZEFRAME:SM_CYFIXEDFRAME)*2
    05574                         + (mbi.rcBar.bottom - mbi.rcBar.top)
    05575                         + r1.Height() - r2.Height()
    05576                         + 1; // ???
    05577 //                      + 2; // ???
    05578                 if(style&WS_CAPTION) h += GetSystemMetrics(SM_CYCAPTION);
    05579
    05580                 if(s.HasFixedWindowSize())
    05581                 {
    05582                         w = s.fixedWindowSize.cx;
    05583                         h = s.fixedWindowSize.cy;
    05584                 }
    05585
    05586                 CRect r;
    05587                 GetWindowRect(r);
    05588
    05589                 int x = r.CenterPoint().x - w/2;
    05590                 int y = r.CenterPoint().y - h/2;
    05591
    05592                 if(s.fRememberWindowPos)
    05593                 {
    05594                         CRect r = s.rcLastWindowPos;
    05595
    05596                         x = r.TopLeft().x;
    05597                         y = r.TopLeft().y;
    05598                 }
    05599
    05600                 MoveWindow(x, y, w, h);
    05601         }
    05602 }
    05603
    05604 OAFilterState CMainFrame::GetMediaState()
    05605 {
    05606         OAFilterState ret = -1;
    05607         if(m_iMediaLoadState == MLS_LOADED) pMC->GetState(0, &ret);
    05608         return(ret);
    05609 }
    05610
    05611 CSize CMainFrame::GetVideoSize()
    05612 {
    05613         bool fKeepAspectRatio = AfxGetAppSettings().fKeepAspectRatio;
    05614         bool fCompMonDeskARDiff = AfxGetAppSettings().fCompMonDeskARDiff;
    05615
    05616         CSize ret(0,0);
    05617         if(m_iMediaLoadState != MLS_LOADED || m_fAudioOnly)
    05618                 return ret;
    05619
    05620         CSize wh(0, 0), arxy(0, 0);
    05621
    05622         if(m_pCAP)
    05623         {
    05624                 wh = m_pCAP->GetVideoSize(false);
    05625                 arxy = m_pCAP->GetVideoSize(fKeepAspectRatio);
    05626         }
    05627         else
    05628         {
    05629                 pBV->GetVideoSize(&wh.cx, &wh.cy);
    05630
    05631                 long arx = 0, ary = 0;
    05632                 CComQIPtr<IBasicVideo2> pBV2 = pBV;
    05633                 if(pBV2 && SUCCEEDED(pBV2->GetPreferredAspectRatio(&arx, &ary)) && arx > 0 && ary > 0)
    05634                         arxy.SetSize(arx, ary);
    05635         }
    05636
    05637         CSize& ar = AfxGetAppSettings().AspectRatio;
    05638         if(ar.cx && ar.cy) arxy = ar;
    05639
    05640         if(wh.cx <= 0 || wh.cy <= 0)
    05641                 return ret;
    05642
    05643         // with the overlay mixer IBasicVideo2 won't tell the new AR when changed dynamically
    05644         DVD_VideoAttributes VATR;
    05645         if(m_iPlaybackMode == PM_DVD && SUCCEEDED(pDVDI->GetCurrentVideoAttributes(&VATR)))
    05646                 arxy.SetSize(VATR.ulAspectX, VATR.ulAspectY);
    05647
    05648         ret = (!fKeepAspectRatio || arxy.cx <= 0 || arxy.cy <= 0)
    05649                 ? wh
    05650                 : CSize(MulDiv(wh.cy, arxy.cx, arxy.cy), wh.cy);
    05651
    05652         if(fCompMonDeskARDiff)
    05653         if(HDC hDC = ::GetDC(0))
    05654         {
    05655                 int _HORZSIZE = GetDeviceCaps(hDC, HORZSIZE);
    05656                 int _VERTSIZE = GetDeviceCaps(hDC, VERTSIZE);
    05657                 int _HORZRES = GetDeviceCaps(hDC, HORZRES);
    05658                 int _VERTRES = GetDeviceCaps(hDC, VERTRES);
    05659
    05660                 if(_HORZSIZE > 0 && _VERTSIZE > 0 && _HORZRES > 0 && _VERTRES > 0)
    05661                 {
    05662                         double a = 1.0*_HORZSIZE/_VERTSIZE;
    05663                         double b = 1.0*_HORZRES/_VERTRES;
    05664
    05665                         if(b < a)
    05666                                 ret.cy = (DWORD)(1.0*ret.cy * a / b);
    05667                         else if(a < b)
    05668                                 ret.cx = (DWORD)(1.0*ret.cx * b / a);
    05669                 }
    05670
    05671                 ::ReleaseDC(0, hDC);
    05672         }
    05673
    05674         return ret;
    05675 }
    05676
    05677 void CMainFrame::ToggleFullscreen(bool fToNearest, bool fSwitchScreenResWhenHasTo)
    05678 {
    05679         CRect r;
    05680 //      const CWnd* pWndInsertAfter;
    05681         DWORD dwRemove = 0, dwAdd = 0;
    05682         DWORD dwRemoveEx = 0, dwAddEx = 0;
    05683         HMENU hMenu;
    05684
    05685         if(!m_fFullScreen)
    05686         {
    05687                 GetWindowRect(&m_lastWindowRect);
    05688
    05689                 dispmode& dm = AfxGetAppSettings().dmFullscreenRes;
    05690                 m_dmBeforeFullscreen.fValid = false;
    05691                 if(dm.fValid && fSwitchScreenResWhenHasTo)
    05692                 {
    05693                         GetCurDispMode(m_dmBeforeFullscreen);
    05694                         SetDispMode(dm);
    05695                 }
    05696
    05697                 MONITORINFO mi;
    05698                 mi.cbSize = sizeof(MONITORINFO);
    05699                 GetMonitorInfo(MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST), &mi);
    05700
    05701                 dwRemove = WS_CAPTION|WS_THICKFRAME;
    05702                 if(fToNearest) r = mi.rcMonitor;
    05703                 else GetDesktopWindow()->GetWindowRect(&r);
    05704                 hMenu = NULL;
    05705         }
    05706         else
    05707         {
    05708                 if(m_dmBeforeFullscreen.fValid)
    05709                         SetDispMode(m_dmBeforeFullscreen);
    05710
    05711                 dwAdd = (AfxGetAppSettings().fHideCaptionMenu ? 0 : WS_CAPTION) | WS_THICKFRAME;
    05712                 r = m_lastWindowRect;
    05713                 hMenu = AfxGetAppSettings().fHideCaptionMenu ? NULL : m_hMenuDefault;
    05714         }
    05715
    05716         m_lastMouseMove.x = m_lastMouseMove.y = -1;
    05717
    05718         bool fAudioOnly = m_fAudioOnly;
    05719         m_fAudioOnly = true;
    05720
    05721         m_fFullScreen = !m_fFullScreen;
    05722
    05723         SetAlwaysOnTop(AfxGetAppSettings().iOnTop);
    05724
    05725         ModifyStyle(dwRemove, dwAdd, SWP_NOZORDER);
    05726         ModifyStyleEx(dwRemoveEx, dwAddEx, SWP_NOZORDER);
    05727         ::SetMenu(m_hWnd, hMenu);
    05728         SetWindowPos(NULL, r.left, r.top, r.Width(), r.Height(), SWP_NOZORDER|SWP_NOSENDCHANGING /*SWP_FRAMECHANGED*/);
    05729
    05730         if(m_fFullScreen)
    05731         {
    05732                 m_fHideCursor = true;
    05733         ShowControls(CS_NONE, false);
    05734         }
    05735         else
    05736         {
    05737                 KillTimer(TIMER_FULLSCREENCONTROLBARHIDER);
    05738                 KillTimer(TIMER_FULLSCREENMOUSEHIDER);
    05739                 m_fHideCursor = false;
    05740         ShowControls(AfxGetAppSettings().nCS);
    05741         }
    05742
    05743         m_wndView.SetWindowPos(NULL, 0, 0, 0, 0, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER);
    05744
    05745         m_fAudioOnly = fAudioOnly;
    05746
    05747         MoveVideoWindow();
    05748 }
    05749
    05750 void CMainFrame::MoveVideoWindow(bool fShowStats)
    05751 {
    05752         if(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly && IsWindowVisible())
    05753         {
    05754                 CRect wr;
    05755                 if(!m_fFullScreen)
    05756                 {
    05757                         m_wndView.GetClientRect(wr);
    05758                         if(!AfxGetAppSettings().fHideCaptionMenu)
    05759                                 wr.DeflateRect(2, 2);
    05760                 }
    05761                 else
    05762                 {
    05763                         GetWindowRect(&wr);
    05764
    05765                         // HACK
    05766                         CRect r;
    05767                         m_wndView.GetWindowRect(&r);
    05768                         wr -= r.TopLeft();
    05769                 }
    05770
    05771                 CRect vr = CRect(0,0,0,0);
    05772
    05773                 OAFilterState fs = GetMediaState();
    05774                 if(fs == State_Paused || fs == State_Running || fs == State_Stopped && (m_fShockwaveGraph || m_fQuicktimeGraph))
    05775                 {
    05776                         CSize arxy = GetVideoSize();
    05777
    05778                         int iDefaultVideoSize = AfxGetAppSettings().iDefaultVideoSize;
    05779
    05780                         CSize ws =
    05781                                 iDefaultVideoSize == DVS_HALF ? CSize(arxy.cx/2, arxy.cy/2) :
    05782                                 iDefaultVideoSize == DVS_NORMAL ? arxy :
    05783                                 iDefaultVideoSize == DVS_DOUBLE ? CSize(arxy.cx*2, arxy.cy*2) :
    05784                                 wr.Size();
    05785
    05786                         int w = ws.cx;
    05787                         int h = ws.cy;
    05788
    05789                         if(!m_fShockwaveGraph) //&& !m_fQuicktimeGraph)
    05790                         {
    05791                                 if(iDefaultVideoSize == DVS_FROMINSIDE || iDefaultVideoSize == DVS_FROMOUTSIDE)
    05792                                 {
    05793                                         h = ws.cy;
    05794                                         w = MulDiv(h, arxy.cx, arxy.cy);
    05795
    05796                                         if(iDefaultVideoSize == DVS_FROMINSIDE && w > ws.cx
    05797                                         || iDefaultVideoSize == DVS_FROMOUTSIDE && w < ws.cx)
    05798                                         {
    05799                                                 w = ws.cx;
    05800                                                 h = MulDiv(w, arxy.cy, arxy.cx);
    05801                                         }
    05802                                 }
    05803                         }
    05804
    05805                         CSize size(
    05806                                 (int)(m_ZoomX*w),
    05807                                 (int)(m_ZoomY*h));
    05808
    05809                         CPoint pos(
    05810                                 (int)(m_PosX*(wr.Width()*3 - m_ZoomX*w) - wr.Width()),
    05811                                 (int)(m_PosY*(wr.Height()*3 - m_ZoomY*h) - wr.Height()));
    05812
    05813 /*                      CPoint pos(
    05814                                 (int)(m_PosX*(wr.Width() - size.cx)),
    05815                                 (int)(m_PosY*(wr.Height() - size.cy)));
    05816
    05817 */
    05818                         vr = CRect(pos, size);
    05819                 }
    05820
    05821                 wr |= CRect(0,0,0,0);
    05822                 vr |= CRect(0,0,0,0);
    05823
    05824                 if(m_pCAP)
    05825                 {
    05826                         m_pCAP->SetPosition(wr, vr);
    05827                 }
    05828                 else
    05829                 {
    05830                         HRESULT hr;
    05831                         hr = pBV->SetDefaultSourcePosition();
    05832                         hr = pBV->SetDestinationPosition(vr.left, vr.top, vr.Width(), vr.Height());
    05833                         hr = pVW->SetWindowPosition(wr.left, wr.top, wr.Width(), wr.Height());
    05834                 }
    05835
    05836                 m_wndView.SetVideoRect(wr);
    05837
    05838                 if(fShowStats && vr.Height() > 0)
    05839                 {
    05840                         CString info;
    05841                         info.Format(_T("Pos %.2f %.2f, Zoom %.2f %.2f, AR %.2f"), m_PosX, m_PosY, m_ZoomX, m_ZoomY, (float)vr.Width()/vr.Height());
    05842                         SendStatusMessage(info, 3000);
    05843                 }
    05844         }
    05845         else
    05846         {
    05847                 m_wndView.SetVideoRect();
    05848         }
    05849 }
    05850
    05851 void CMainFrame::ZoomVideoWindow(double scale)
    05852 {
    05853         if(m_iMediaLoadState != MLS_LOADED)
    05854                 return;
    05855
    05856         AppSettings& s = AfxGetAppSettings();
    05857
    05858         if(scale <= 0)
    05859         {
    05860                 scale = s.iZoomLevel == 0 ? 0.5 : s.iZoomLevel == 2 ? 2.0 : 1.0;
    05861         }
    05862
    05863         if(m_fFullScreen)
    05864         {
    05865                 OnViewFullscreen();
    05866         }
    05867
    05868         MINMAXINFO mmi;
    05869         OnGetMinMaxInfo(&mmi);
    05870
    05871         CRect r;
    05872         int w = 0, h = 0;
    05873
    05874         if(!m_fAudioOnly)
    05875         {
    05876                 CSize arxy = GetVideoSize();
    05877
    05878                 long lWidth = int(arxy.cx * scale + 0.5);
    05879                 long lHeight = int(arxy.cy * scale + 0.5);
    05880
    05881                 DWORD style = GetStyle();
    05882
    05883                 CRect r1, r2;
    05884                 GetClientRect(&r1);
    05885                 m_wndView.GetClientRect(&r2);
    05886
    05887                 w = GetSystemMetrics((style&WS_CAPTION)?SM_CXSIZEFRAME:SM_CXFIXEDFRAME)*2
    05888                                 + r1.Width() - r2.Width()
    05889                                 + lWidth;
    05890
    05891                 MENUBARINFO mbi;
    05892                 memset(&mbi, 0, sizeof(mbi));
    05893                 mbi.cbSize = sizeof(mbi);
    05894                 ::GetMenuBarInfo(m_hWnd, OBJID_MENU, 0, &mbi);
    05895
    05896                 h = GetSystemMetrics((style&WS_CAPTION)?SM_CYSIZEFRAME:SM_CYFIXEDFRAME)*2
    05897                                 + (mbi.rcBar.bottom - mbi.rcBar.top)
    05898                                 + r1.Height() - r2.Height()
    05899                                 + lHeight;
    05900
    05901                 if(style&WS_CAPTION)
    05902                 {
    05903                         h += GetSystemMetrics(SM_CYCAPTION);
    05904                         w += 2; h += 2; // for the 1 pixel wide sunken frame
    05905                         w += 2; h += 3; // for the inner black border
    05906                 }
    05907
    05908                 GetWindowRect(r);
    05909
    05910                 w = max(w, mmi.ptMinTrackSize.x);
    05911                 h = max(h, mmi.ptMinTrackSize.y);
    05912         }
    05913         else
    05914         {
    05915                 GetWindowRect(r);
    05916
    05917                 w = r.Width(); // mmi.ptMinTrackSize.x;
    05918                 h = mmi.ptMinTrackSize.y;
    05919         }
    05920
    05921         // center window
    05922         if(!s.fRememberWindowPos)
    05923         {
    05924                 CPoint cp = r.CenterPoint();
    05925                 r.left = cp.x - w/2;
    05926                 r.top = cp.y - h/2;
    05927         }
    05928
    05929         r.right = r.left + w;
    05930         r.bottom = r.top + h;
    05931
    05932         MONITORINFO mi;
    05933         mi.cbSize = sizeof(MONITORINFO);
    05934         GetMonitorInfo(MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST), &mi);
    05935         if(r.right > mi.rcWork.right) r.OffsetRect(mi.rcWork.right-r.right, 0);
    05936         if(r.left < mi.rcWork.left) r.OffsetRect(mi.rcWork.left-r.left, 0);
    05937         if(r.bottom > mi.rcWork.bottom) r.OffsetRect(0, mi.rcWork.bottom-r.bottom);
    05938         if(r.top < mi.rcWork.top) r.OffsetRect(0, mi.rcWork.top-r.top);
    05939
    05940         if(m_fFullScreen || !s.HasFixedWindowSize())
    05941         {
    05942                 MoveWindow(r);
    05943         }
    05944
    05945 //      ShowWindow(SW_SHOWNORMAL);
    05946
    05947         MoveVideoWindow();
    05948 }
    05949
    05950 void CMainFrame::RepaintVideo()
    05951 {
    05952         if(m_pCAP) m_pCAP->Paint(false);
    05953 }
    05954
    05955 void CMainFrame::SetBalance(int balance)
    05956 {
    05957         AfxGetAppSettings().nBalance = balance;
    05958
    05959         int sign = balance>0?-1:1;
    05960         balance = max(100-abs(balance), 1);
    05961         balance = (int)((log10(1.0*balance)-2)*5000*sign);
    05962         balance = max(min(balance, 10000), -10000);
    05963
    05964         if(m_iMediaLoadState == MLS_LOADED)
    05965                 pBA->put_Balance(balance);
    05966 }
    05967
    05968 void CMainFrame::SetupIViAudReg()
    05969 {
    05970         if(!AfxGetAppSettings().fAutoSpeakerConf) return;
    05971
    05972         DWORD spc = 0, defchnum = 0;
    05973
    05974         if(AfxGetAppSettings().fAutoSpeakerConf)
    05975         {
    05976                 CComPtr<IDirectSound> pDS;
    05977                 if(SUCCEEDED(DirectSoundCreate(NULL, &pDS, NULL))
    05978                 && SUCCEEDED(pDS->SetCooperativeLevel(m_hWnd, DSSCL_NORMAL)))
    05979                 {
    05980                         if(SUCCEEDED(pDS->GetSpeakerConfig(&spc)))
    05981                         {
    05982                                 switch(spc)
    05983                                 {
    05984                                 case DSSPEAKER_DIRECTOUT: defchnum = 6; break;
    05985                                 case DSSPEAKER_HEADPHONE: defchnum = 2; break;
    05986                                 case DSSPEAKER_MONO: defchnum = 1; break;
    05987                                 case DSSPEAKER_QUAD: defchnum = 4; break;
    05988                                 default:
    05989                                 case DSSPEAKER_STEREO: defchnum = 2; break;
    05990                                 case DSSPEAKER_SURROUND: defchnum = 2; break;
    05991                                 case DSSPEAKER_5POINT1: defchnum = 5; break;
    05992                                 case DSSPEAKER_7POINT1: defchnum = 5; break;
    05993                                 }
    05994                         }
    05995                 }
    05996         }
    05997         else
    05998         {
    05999                 defchnum = 2;
    06000         }
    06001
    06002         CRegKey iviaud;
    06003         if(ERROR_SUCCESS == iviaud.Create(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\InterVideo\\Common\\AudioDec")))
    06004         {
    06005                 DWORD chnum = 0;
    06006                 if(FAILED(iviaud.QueryDWORDValue(_T("AUDIO"), chnum))) chnum = 0;
    06007                 if(chnum <= defchnum) // check if the user has already set it..., but we won't skip if it's lower than sensible :P
    06008                         iviaud.SetDWORDValue(_T("AUDIO"), defchnum);
    06009         }
    06010 }
    06011
    06012 //
    06013 // Open/Close
    06014 //
    06015
    06016 void CMainFrame::OpenCreateGraphObject(OpenMediaData* pOMD)
    06017 {
    06018         pGB = NULL;
    06019
    06020         m_fCustomGraph = false;
    06021         m_fRealMediaGraph = m_fShockwaveGraph = m_fQuicktimeGraph = false;
    06022
    06023         if(OpenFileData* p = dynamic_cast<OpenFileData*>(pOMD))
    06024         {
    06025                 AppSettings& s = AfxGetAppSettings();
    06026
    06027                 engine_t engine = s.Formats.GetEngine(p->fns.GetHead());
    06028
    06029                 CStringA ct = GetContentType(p->fns.GetHead());
    06030
    06031                 if(ct == "video/x-ms-asf")
    06032                 {
    06033                         // TODO: put something here to make the windows media source filter load later
    06034                 }
    06035                 else if(ct == "audio/x-pn-realaudio"
    06036                 || ct == "audio/x-pn-realaudio-plugin"
    06037                 || ct == "audio/x-realaudio-secure"
    06038                 || ct == "video/vnd.rn-realvideo-secure"
    06039                 || ct == "application/vnd.rn-realmedia"
    06040                 || ct.Find("vnd.rn-") >= 0
    06041                 || ct.Find("realaudio") >= 0
    06042                 || ct.Find("realvideo") >= 0)
    06043                 {
    06044                         engine = RealMedia;
    06045                 }
    06046                 else if(ct == "application/x-shockwave-flash")
    06047                 {
    06048                         engine = ShockWave;
    06049                 }
    06050                 else if(ct == "video/quicktime"
    06051                         || ct == "application/x-quicktimeplayer")
    06052                 {
    06053                         engine = QuickTime;
    06054                 }
    06055
    06056                 HRESULT hr;
    06057                 CComPtr<IUnknown> pUnk;
    06058
    06059                 if(engine == RealMedia)
    06060                 {
    06061                         if(!(pUnk = (IUnknown*)(INonDelegatingUnknown*)new CRealMediaGraph(m_wndView.m_hWnd, hr)))
    06062                                 throw _T("Out of memory");
    06063
    06064                         m_pCAP = CComQIPtr<ISubPicAllocatorPresenter>(pUnk);
    06065
    06066 //                      if(FAILED(hr) || !(pGB = CComQIPtr<IGraphBuilder>(pUnk)))
    06067 //                              throw _T("RealMedia files require RealPlayer/RealOne to be installed");
    06068                         if(SUCCEEDED(hr) && !!(pGB = CComQIPtr<IGraphBuilder>(pUnk)))
    06069                                 m_fRealMediaGraph = true;
    06070                 }
    06071                 else if(engine == ShockWave)
    06072                 {
    06073                         if(!(pUnk = (IUnknown*)(INonDelegatingUnknown*)new CShockwaveGraph(m_wndView.m_hWnd, hr)))
    06074                                 throw _T("Out of memory");
    06075
    06076                         if(FAILED(hr) || !(pGB = CComQIPtr<IGraphBuilder>(pUnk)))
    06077                                 throw _T("Can't create shockwave control");
    06078
    06079                         m_fShockwaveGraph = true;
    06080                 }
    06081                 else if(engine == QuickTime)
    06082                 {
    06083                         if(!(pUnk = (IUnknown*)(INonDelegatingUnknown*)new CQuicktimeGraph(m_wndView.m_hWnd, hr)))
    06084                                 throw _T("Out of memory");
    06085
    06086                         m_pCAP = CComQIPtr<ISubPicAllocatorPresenter>(pUnk);
    06087
    06088 //                      if(FAILED(hr) || !(pGB = CComQIPtr<IGraphBuilder>(pUnk)))
    06089 //                              throw _T("Can't initialize QuickTime");
    06090                         if(SUCCEEDED(hr) && !!(pGB = CComQIPtr<IGraphBuilder>(pUnk)))
    06091                 m_fQuicktimeGraph = true;
    06092                 }
    06093
    06094                 m_fCustomGraph = m_fRealMediaGraph || m_fShockwaveGraph || m_fQuicktimeGraph;
    06095         }
    06096
    06097         if(!m_fCustomGraph)
    06098         {
    06099                 if(FAILED(pGB.CoCreateInstance(CLSID_FilterGraph)))
    06100                 {
    06101                         throw _T("Failed to create the filter graph object");
    06102                 }
    06103         }
    06104
    06105         pMC = pGB; pME = pGB; pMS = pGB; // general
    06106         pVW = pGB; pBV = pGB; // video
    06107         pBA = pGB; // audio
    06108         pFS = pGB;
    06109
    06110         if(!(pMC && pME && pMS)
    06111         || !(pVW && pBV)
    06112         || !(pBA))
    06113         {
    06114                 throw _T("Failed to query the needed interfaces for playback");
    06115         }
    06116
    06117         if(FAILED(pME->SetNotifyWindow((OAHWND)m_hWnd, WM_GRAPHNOTIFY, 0)))
    06118         {
    06119                 throw _T("Could not set target window for graph notification");
    06120         }
    06121
    06122         m_pProv = (IUnknown*)new CKeyProvider();
    06123
    06124         if(CComQIPtr<IObjectWithSite> pObjectWithSite = pGB)
    06125                 pObjectWithSite->SetSite(m_pProv);
    06126
    06127         m_pCB = new CDSMChapterBag(NULL, NULL);
    06128 }
    06129
    06130 void CMainFrame::OpenFile(OpenFileData* pOFD)
    06131 {
    06132         if(pOFD->fns.IsEmpty())
    06133                 throw _T("Invalid argument");
    06134
    06135         AppSettings& s = AfxGetAppSettings();
    06136
    06137     CGraphBuilderFile gb(pGB, m_wndView.m_hWnd);
    06138
    06139         bool fFirst = true;
    06140
    06141         POSITION pos = pOFD->fns.GetHeadPosition();
    06142         while(pos)
    06143         {
    06144                 CString fn = pOFD->fns.GetNext(pos);
    06145
    06146                 fn.Trim();
    06147                 if(fn.IsEmpty() && !fFirst)
    06148                         break;
    06149
    06150                 HRESULT hr = gb.Render(fn);
    06151
    06152                 if(FAILED(hr))
    06153                 {
    06154                         if(fFirst)
    06155                         {
    06156                                 if(s.fReportFailedPins && gb.GetDeadEnd(0))
    06157                                 {
    06158                                         CMediaTypesDlg(gb, this).DoModal();
    06159
    06160                                         if(gb.GetStreamCount() == 0)
    06161                                                 throw _T("Cannot render any of the streams");
    06162                                 }
    06163
    06164                                 CString err;
    06165
    06166                                 switch(hr)
    06167                                 {
    06168                                 case E_ABORT: err = _T("Opening aborted"); break;
    06169                                 case E_FAIL: case E_POINTER: default: err = _T("Failed to render the file"); break;
    06170                                 case E_INVALIDARG: err = _T("Invalid file name"); break;
    06171                                 case E_OUTOFMEMORY: err = _T("Out of memory"); break;
    06172                                 case VFW_E_CANNOT_CONNECT: err = _T("Cannot connect the filters"); break;
    06173                                 case VFW_E_CANNOT_LOAD_SOURCE_FILTER: err = _T("Cannot load any source filter"); break;
    06174                                 case VFW_E_CANNOT_RENDER: err = _T("Cannot render the file"); break;
    06175                                 case VFW_E_INVALID_FILE_FORMAT: err = _T("Invalid file format"); break;
    06176                                 case VFW_E_NOT_FOUND: err = _T("File not found"); break;
    06177                                 case VFW_E_UNKNOWN_FILE_TYPE: err = _T("Unknown file type"); break;
    06178                                 case VFW_E_UNSUPPORTED_STREAM: err = _T("Unsupported stream"); break;
    06179                                 }
    06180
    06181                                 throw err;
    06182                         }
    06183                 }
    06184
    06185                 if(s.fKeepHistory)
    06186                 {
    06187                         CRecentFileList* pMRU = fFirst ? &s.MRU : &s.MRUDub;
    06188                         pMRU->ReadList();
    06189                         pMRU->Add(fn);
    06190                         pMRU->WriteList();
    06191                 }
    06192
    06193                 if(fFirst)
    06194                 {
    06195                         pOFD->title = fn;
    06196                 }
    06197
    06198                 fFirst = false;
    06199
    06200                 if(m_fCustomGraph) break;
    06201         }
    06202
    06203         if(s.fReportFailedPins && gb.GetDeadEnd(0))
    06204                 CMediaTypesDlg(gb, this).DoModal();
    06205
    06206         if(!m_fCustomGraph)
    06207                 gb.FindInterface(__uuidof(ISubPicAllocatorPresenter), (void**)&m_pCAP);
    06208
    06209         if(!(pAMOP = pGB))
    06210         {
    06211                 BeginEnumFilters(pGB, pEF, pBF)
    06212                         if(pAMOP = pBF) break;
    06213                 EndEnumFilters
    06214         }
    06215
    06216         if(FindFilter(__uuidof(CShoutcastSource), pGB))
    06217                 m_fUpdateInfoBar = true;
    06218
    06219         SetupChapters();
    06220
    06221         CComQIPtr<IKeyFrameInfo> pKFI;
    06222         BeginEnumFilters(pGB, pEF, pBF)
    06223                 if(pKFI = pBF) break;
    06224         EndEnumFilters
    06225         UINT nKFs = 0, nKFsTmp = 0;
    06226         if(pKFI && S_OK == pKFI->GetKeyFrameCount(nKFs) && nKFs > 0)
    06227         {
    06228                 m_kfs.SetSize(nKFsTmp = nKFs);
    06229                 if(S_OK != pKFI->GetKeyFrames(&TIME_FORMAT_MEDIA_TIME, m_kfs.GetData(), nKFsTmp) || nKFsTmp != nKFs)
    06230                         m_kfs.SetSize(0);
    06231         }
    06232
    06233         m_iPlaybackMode = PM_FILE;
    06234 }
    06235
    06236 void CMainFrame::SetupChapters()
    06237 {
    06238         ASSERT(m_pCB);
    06239
    06240         m_pCB->ChapRemoveAll();
    06241
    06242         CInterfaceList<IBaseFilter> pBFs;
    06243         BeginEnumFilters(pGB, pEF, pBF)
    06244                 pBFs.AddTail(pBF);
    06245         EndEnumFilters
    06246
    06247         POSITION pos;
    06248
    06249         pos = pBFs.GetHeadPosition();
    06250         while(pos && !m_pCB->ChapGetCount())
    06251         {
    06252                 IBaseFilter* pBF = pBFs.GetNext(pos);
    06253
    06254                 CComQIPtr<IDSMChapterBag> pCB = pBF;
    06255                 if(!pCB) continue;
    06256
    06257                 for(DWORD i = 0, cnt = pCB->ChapGetCount(); i < cnt; i++)
    06258                 {
    06259                         REFERENCE_TIME rt;
    06260                         CComBSTR name;
    06261                         if(SUCCEEDED(pCB->ChapGet(i, &rt, &name)))
    06262                                 m_pCB->ChapAppend(rt, name);
    06263                 }
    06264         }
    06265
    06266         pos = pBFs.GetHeadPosition();
    06267         while(pos && !m_pCB->ChapGetCount())
    06268         {
    06269                 IBaseFilter* pBF = pBFs.GetNext(pos);
    06270
    06271                 CComQIPtr<IChapterInfo> pCI = pBF;
    06272                 if(!pCI) continue;
    06273
    06274                 CHAR iso6391[3];
    06275                 ::GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SISO639LANGNAME, iso6391, 3);
    06276                 CStringA iso6392 = ISO6391To6392(iso6391);
    06277                 if(iso6392.GetLength() < 3) iso6392 = "eng";
    06278
    06279                 UINT cnt = pCI->GetChapterCount(CHAPTER_ROOT_ID);
    06280                 for(UINT i = 1; i <= cnt; i++)
    06281                 {
    06282                         UINT cid = pCI->GetChapterId(CHAPTER_ROOT_ID, i);
    06283
    06284                         ChapterElement ce;
    06285                         if(pCI->GetChapterInfo(cid, &ce))
    06286                         {
    06287                                 char pl[3] = {iso6392[0], iso6392[1], iso6392[2]};
    06288                                 char cc[] = "  ";
    06289                                 CComBSTR name;
    06290                                 name.Attach(pCI->GetChapterStringInfo(cid, pl, cc));
    06291                                 m_pCB->ChapAppend(ce.rtStart, name);
    06292                         }
    06293                 }
    06294         }
    06295
    06296         pos = pBFs.GetHeadPosition();
    06297         while(pos && !m_pCB->ChapGetCount())
    06298         {
    06299                 IBaseFilter* pBF = pBFs.GetNext(pos);
    06300
    06301                 CComQIPtr<IAMExtendedSeeking, &IID_IAMExtendedSeeking> pES = pBF;
    06302                 if(!pES) continue;
    06303
    06304                 long MarkerCount = 0;
    06305                 if(SUCCEEDED(pES->get_MarkerCount(&MarkerCount)))
    06306                 {
    06307                         for(long i = 1; i <= MarkerCount; i++)
    06308                         {
    06309                                 double MarkerTime = 0;
    06310                                 if(SUCCEEDED(pES->GetMarkerTime(i, &MarkerTime)))
    06311                                 {
    06312                                         CStringW name;
    06313                                         name.Format(L"Chapter %d", i);
    06314
    06315                                         CComBSTR bstr;
    06316                                         if(S_OK == pES->GetMarkerName(i, &bstr))
    06317                                                 name = bstr;
    06318
    06319                                         m_pCB->ChapAppend(REFERENCE_TIME(MarkerTime*10000000), name);
    06320                                 }
    06321                         }
    06322                 }
    06323         }
    06324
    06325         pos = pBFs.GetHeadPosition();
    06326         while(pos && !m_pCB->ChapGetCount())
    06327         {
    06328                 IBaseFilter* pBF = pBFs.GetNext(pos);
    06329
    06330                 if(GetCLSID(pBF) != CLSID_OggSplitter)
    06331                         continue;
    06332
    06333                 BeginEnumPins(pBF, pEP, pPin)
    06334                 {
    06335                         if(m_pCB->ChapGetCount()) break;
    06336
    06337                         if(CComQIPtr<IPropertyBag> pPB = pPin)
    06338                         {
    06339                 for(int i = 1; ; i++)
    06340                                 {
    06341                                         CStringW str;
    06342                                         CComVariant var;
    06343
    06344                                         var.Clear();
    06345                                         str.Format(L"CHAPTER%02d", i);
    06346                                         if(S_OK != pPB->Read(str, &var, NULL))
    06347                                                 break;
    06348
    06349                                         int h, m, s, ms;
    06350                                         WCHAR wc;
    06351                                         if(7 != swscanf(CStringW(var), L"%d%c%d%c%d%c%d", &h, &wc, &m, &wc, &s, &wc, &ms))
    06352                                                 break;
    06353
    06354                                         CStringW name;
    06355                                         name.Format(L"Chapter %d", i);
    06356                                         var.Clear();
    06357                     str += L"NAME";
    06358                                         if(S_OK == pPB->Read(str, &var, NULL))
    06359                                                 name = var;
    06360
    06361                                         m_pCB->ChapAppend(10000i64*(((h*60 + m)*60 + s)*1000 + ms), name);
    06362                                 }
    06363                         }
    06364                 }
    06365                 EndEnumPins
    06366         }
    06367
    06368         m_pCB->ChapSort();
    06369 }
    06370
    06371 void CMainFrame::OpenDVD(OpenDVDData* pODD)
    06372 {
    06373         CGraphBuilderDVD gb(pGB, m_wndView.m_hWnd);
    06374
    06375         HRESULT hr = gb.Render(pODD->path, pODD->title);
    06376
    06377         AppSettings& s = AfxGetAppSettings();
    06378
    06379         if(hr == VFW_E_CANNOT_LOAD_SOURCE_FILTER)
    06380                 throw _T("Can't find DVD directory");
    06381         else if(hr == VFW_E_CANNOT_RENDER)
    06382                 throw _T("Failed to render all pins of the DVD Navigator filter");
    06383         else if(hr == VFW_S_PARTIAL_RENDER)
    06384         {
    06385                 if(s.fReportFailedPins && gb.GetDeadEnd(0))
    06386                         CMediaTypesDlg(gb, this).DoModal();
    06387
    06388                 throw _T("Failed to render some of the pins of the DVD Navigator filter");
    06389         }
    06390         else if(hr == E_NOINTERFACE)
    06391                 throw _T("Failed to query the needed interfaces for DVD playback");
    06392         else if(FAILED(hr))
    06393                 throw _T("Can't create the DVD Navigator filter");
    06394
    06395         gb.FindInterface(__uuidof(ISubPicAllocatorPresenter), (void**)&m_pCAP);
    06396         gb.FindInterface(__uuidof(IDvdControl2), (void**)&pDVDC);
    06397         gb.FindInterface(__uuidof(IDvdInfo2), (void**)&pDVDI);
    06398
    06399         if(!pDVDC || !pDVDI)
    06400                 throw _T("Failed to query the needed interfaces for DVD playback");
    06401
    06402         if(s.idMenuLang)
    06403                 pDVDC->SelectDefaultMenuLanguage(s.idMenuLang);
    06404         if(s.idAudioLang)
    06405                 pDVDC->SelectDefaultAudioLanguage(s.idAudioLang, DVD_AUD_EXT_NotSpecified);
    06406         if(s.idSubtitlesLang)
    06407                 pDVDC->SelectDefaultSubpictureLanguage(s.idSubtitlesLang, DVD_SP_EXT_NotSpecified);
    06408
    06409         m_iDVDDomain = DVD_DOMAIN_Stop;
    06410
    06411         m_iPlaybackMode = PM_DVD;
    06412 }
    06413
    06414 void CMainFrame::OpenCapture(OpenDeviceData* pODD)
    06415 {
    06416         CStringW vidfrname, audfrname;
    06417         CComPtr<IBaseFilter> pVidCapTmp, pAudCapTmp;
    06418
    06419         m_VidDispName = pODD->DisplayName[0];
    06420
    06421         if(!m_VidDispName.IsEmpty())
    06422         {
    06423                 if(!CreateFilter(m_VidDispName, &pVidCapTmp, vidfrname))
    06424                         throw _T("Can't create video capture filter");
    06425         }
    06426
    06427         m_AudDispName = pODD->DisplayName[1];
    06428
    06429         if(!m_AudDispName.IsEmpty())
    06430         {
    06431                 if(!CreateFilter(m_AudDispName, &pAudCapTmp, audfrname))
    06432                         throw _T("Can't create video capture filter");
    06433         }
    06434
    06435         if(!pVidCapTmp && !pAudCapTmp)
    06436         {
    06437                 throw _T("No capture filters");
    06438         }
    06439
    06440         pCGB = NULL;
    06441         pVidCap = NULL;
    06442         pAudCap = NULL;
    06443
    06444         if(FAILED(pCGB.CoCreateInstance(CLSID_CaptureGraphBuilder2)))
    06445         {
    06446                 throw _T("Can't create capture graph builder object");
    06447         }
    06448
    06449         HRESULT hr;
    06450
    06451         pCGB->SetFiltergraph(pGB);
    06452
    06453         if(pVidCapTmp)
    06454         {
    06455                 if(FAILED(hr = pGB->AddFilter(pVidCapTmp, vidfrname)))
    06456                 {
    06457                         throw _T("Can't add video capture filter to the graph");
    06458                 }
    06459
    06460                 pVidCap = pVidCapTmp;
    06461
    06462                 if(!pAudCapTmp)
    06463                 {
    06464                         if(FAILED(pCGB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Interleaved, pVidCap, IID_IAMStreamConfig, (void **)&pAMVSCCap))
    06465                         && FAILED(pCGB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pVidCap, IID_IAMStreamConfig, (void **)&pAMVSCCap)))
    06466                                 TRACE(_T("Warning: No IAMStreamConfig interface for vidcap capture"));
    06467
    06468                         if(FAILED(pCGB->FindInterface(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Interleaved, pVidCap, IID_IAMStreamConfig, (void **)&pAMVSCPrev))
    06469                         && FAILED(pCGB->FindInterface(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, pVidCap, IID_IAMStreamConfig, (void **)&pAMVSCPrev)))
    06470                                 TRACE(_T("Warning: No IAMStreamConfig interface for vidcap capture"));
    06471
    06472                         if(FAILED(pCGB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, pVidCap, IID_IAMStreamConfig, (void **)&pAMASC))
    06473                         && FAILED(pCGB->FindInterface(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Audio, pVidCap, IID_IAMStreamConfig, (void **)&pAMASC)))
    06474                         {
    06475                                 TRACE(_T("Warning: No IAMStreamConfig interface for vidcap"));
    06476                         }
    06477                         else
    06478                         {
    06479                                 pAudCap = pVidCap;
    06480                         }
    06481                 }
    06482                 else
    06483                 {
    06484                         if(FAILED(pCGB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pVidCap, IID_IAMStreamConfig, (void **)&pAMVSCCap)))
    06485                                 TRACE(_T("Warning: No IAMStreamConfig interface for vidcap capture"));
    06486
    06487                         if(FAILED(pCGB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pVidCap, IID_IAMStreamConfig, (void **)&pAMVSCPrev)))
    06488                                 TRACE(_T("Warning: No IAMStreamConfig interface for vidcap capture"));
    06489                 }
    06490
    06491                 if(FAILED(pCGB->FindInterface(&LOOK_UPSTREAM_ONLY, NULL, pVidCap, IID_IAMCrossbar, (void**)&pAMXBar)))
    06492                         TRACE(_T("Warning: No IAMCrossbar interface was found\n"));
    06493
    06494                 if(FAILED(pCGB->FindInterface(&LOOK_UPSTREAM_ONLY, NULL, pVidCap, IID_IAMTVTuner, (void**)&pAMTuner)))
    06495                         TRACE(_T("Warning: No IAMTVTuner interface was found\n"));
    06496 /*
    06497                 if(pAMVSCCap)
    06498                 {
    06499 //DumpStreamConfig(_T("c:\\mpclog.txt"), pAMVSCCap);
    06500             CComQIPtr<IAMVfwCaptureDialogs> pVfwCD = pVidCap;
    06501                         if(!pAMXBar && pVfwCD)
    06502                         {
    06503                                 m_wndCaptureBar.m_capdlg.SetupVideoControls(viddispname, pAMVSCCap, pVfwCD);
    06504                         }
    06505                         else
    06506                         {
    06507                                 m_wndCaptureBar.m_capdlg.SetupVideoControls(viddispname, pAMVSCCap, pAMXBar, pAMTuner);
    06508                         }
    06509                 }
    06510 */
    06511                 // TODO: init pAMXBar
    06512
    06513                 if(pAMTuner) // load saved channel
    06514                 {
    06515                         pAMTuner->put_CountryCode(AfxGetApp()->GetProfileInt(_T("Capture"), _T("Country"), 1));
    06516
    06517                         int vchannel = pODD->vchannel;
    06518                         if(vchannel < 0) vchannel = AfxGetApp()->GetProfileInt(_T("Capture\\") + CString(m_VidDispName), _T("Channel"), -1);
    06519                         if(vchannel >= 0)
    06520                         {
    06521                                 OAFilterState fs = State_Stopped;
    06522                                 pMC->GetState(0, &fs);
    06523                                 if(fs == State_Running) pMC->Pause();
    06524                                 pAMTuner->put_Channel(vchannel, AMTUNER_SUBCHAN_DEFAULT, AMTUNER_SUBCHAN_DEFAULT);
    06525                                 if(fs == State_Running) pMC->Run();
    06526                         }
    06527                 }
    06528         }
    06529
    06530         if(pAudCapTmp)
    06531         {
    06532                 if(FAILED(hr = pGB->AddFilter(pAudCapTmp, CStringW(audfrname))))
    06533                 {
    06534                         throw _T("Can't add audio capture filter to the graph");
    06535                 }
    06536
    06537                 pAudCap = pAudCapTmp;
    06538
    06539                 if(FAILED(pCGB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, pAudCap, IID_IAMStreamConfig, (void **)&pAMASC))
    06540                 && FAILED(pCGB->FindInterface(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Audio, pAudCap, IID_IAMStreamConfig, (void **)&pAMASC)))
    06541                 {
    06542                         TRACE(_T("Warning: No IAMStreamConfig interface for vidcap"));
    06543                 }
    06544 /*
    06545                 CInterfaceArray<IAMAudioInputMixer> pAMAIM;
    06546
    06547                 BeginEnumPins(pAudCap, pEP, pPin)
    06548                 {
    06549                         PIN_DIRECTION dir;
    06550                         if(FAILED(pPin->QueryDirection(&dir)) || dir != PINDIR_INPUT)
    06551                                 continue;
    06552
    06553                         if(CComQIPtr<IAMAudioInputMixer> pAIM = pPin)
    06554                                 pAMAIM.Add(pAIM);
    06555                 }
    06556                 EndEnumPins
    06557
    06558                 if(pAMASC)
    06559                 {
    06560                         m_wndCaptureBar.m_capdlg.SetupAudioControls(auddispname, pAMASC, pAMAIM);
    06561                 }
    06562 */
    06563         }
    06564
    06565         if(!(pVidCap || pAudCap))
    06566         {
    06567                 throw _T("Couldn't open any device");
    06568         }
    06569
    06570         pODD->title = _T("Live");
    06571
    06572         m_iPlaybackMode = PM_CAPTURE;
    06573 }
    06574
    06575 void CMainFrame::OpenCustomizeGraph()
    06576 {
    06577         if(m_iPlaybackMode == PM_CAPTURE)
    06578                 return;
    06579
    06580         CleanGraph();
    06581
    06582         if(m_iPlaybackMode == PM_FILE)
    06583         {
    06584                 if(m_pCAP)
    06585                         AddTextPassThruFilter();
    06586         }
    06587
    06588         if(m_iPlaybackMode == PM_DVD)
    06589         {
    06590                 BeginEnumFilters(pGB, pEF, pBF)
    06591                 {
    06592                         if(CComQIPtr<IDirectVobSub2> pDVS2 = pBF)
    06593                         {
    06594 //                              pDVS2->AdviseSubClock(m_pSubClock = new CSubClock);
    06595 //                              break;
    06596
    06597                                 // TODO: test multiple dvobsub instances with one clock
    06598                                 if(!m_pSubClock) m_pSubClock = new CSubClock;
    06599                                 pDVS2->AdviseSubClock(m_pSubClock);
    06600                         }
    06601                 }
    06602                 EndEnumFilters
    06603         }
    06604
    06605         BeginEnumFilters(pGB, pEF, pBF)
    06606         {
    06607                 if(GetCLSID(pBF) == CLSID_OggSplitter)
    06608                 {
    06609                         if(CComQIPtr<IAMStreamSelect> pSS = pBF)
    06610                         {
    06611                                 LCID idAudio = AfxGetAppSettings().idAudioLang;
    06612                                 if(!idAudio) idAudio = GetUserDefaultLCID();
    06613                                 LCID idSub = AfxGetAppSettings().idSubtitlesLang;
    06614                                 if(!idSub) idSub = GetUserDefaultLCID();
    06615
    06616                                 DWORD cnt = 0;
    06617                                 pSS->Count(&cnt);
    06618                                 for(DWORD i = 0; i < cnt; i++)
    06619                                 {
    06620                                         AM_MEDIA_TYPE* pmt = NULL;
    06621                                         DWORD dwFlags = 0;
    06622                                         LCID lcid = 0;
    06623                                         DWORD dwGroup = 0;
    06624                                         WCHAR* pszName = NULL;
    06625                                         if(SUCCEEDED(pSS->Info((long)i, &pmt, &dwFlags, &lcid, &dwGroup, &pszName, NULL, NULL)))
    06626                                         {
    06627                                                 CStringW name(pszName), sound(L"Sound"), subtitle(L"Subtitle");
    06628
    06629                                                 if(idAudio != -1 && (idAudio&0x3ff) == (lcid&0x3ff) // sublang seems to be zeroed out in ogm...
    06630                                                 && name.GetLength() > sound.GetLength()
    06631                                                 && !name.Left(sound.GetLength()).CompareNoCase(sound))
    06632                                                 {
    06633                                                         if(SUCCEEDED(pSS->Enable(i, AMSTREAMSELECTENABLE_ENABLE)))
    06634                                                                 idAudio = -1;
    06635                                                 }
    06636
    06637                                                 if(idSub != -1 && (idSub&0x3ff) == (lcid&0x3ff) // sublang seems to be zeroed out in ogm...
    06638                                                 && name.GetLength() > subtitle.GetLength()
    06639                                                 && !name.Left(subtitle.GetLength()).CompareNoCase(subtitle)
    06640                                                 && name.Mid(subtitle.GetLength()).Trim().CompareNoCase(L"off"))
    06641                                                 {
    06642                                                         if(SUCCEEDED(pSS->Enable(i, AMSTREAMSELECTENABLE_ENABLE)))
    06643                                                                 idSub = -1;
    06644                                                 }
    06645
    06646                                                 if(pmt) DeleteMediaType(pmt);
    06647                                                 if(pszName) CoTaskMemFree(pszName);
    06648                                         }
    06649                                 }
    06650                         }
    06651                 }
    06652         }
    06653         EndEnumFilters
    06654
    06655         CleanGraph();
    06656 }
    06657
    06658 void CMainFrame::OpenSetupVideo()
    06659 {
    06660         m_fAudioOnly = true;
    06661
    06662         if(m_pCAP)
    06663         {
    06664                 CSize vs = m_pCAP->GetVideoSize();
    06665                 m_fAudioOnly = (vs.cx <= 0 || vs.cy <= 0);
    06666         }
    06667         else
    06668         {
    06669                 {
    06670                         long w = 0, h = 0;
    06671
    06672                         if(CComQIPtr<IBasicVideo> pBV = pGB)
    06673                         {
    06674                                 pBV->GetVideoSize(&w, &h);
    06675                         }
    06676
    06677                         if(w > 0 && h > 0)
    06678                         {
    06679                                 m_fAudioOnly = false;
    06680                         }
    06681                 }
    06682
    06683                 if(m_fAudioOnly)
    06684                 {
    06685                         BeginEnumFilters(pGB, pEF, pBF)
    06686                         {
    06687                                 long w = 0, h = 0;
    06688
    06689                                 if(CComQIPtr<IVideoWindow> pVW = pBF)
    06690                                 {
    06691                                         long lVisible;
    06692                                         if(FAILED(pVW->get_Visible(&lVisible)))
    06693                                                 continue;
    06694
    06695                                         pVW->get_Width(&w);
    06696                                         pVW->get_Height(&h);
    06697                                 }
    06698
    06699                                 if(w > 0 && h > 0)
    06700                                 {
    06701                                         m_fAudioOnly = false;
    06702                                         break;
    06703                                 }
    06704                         }
    06705                         EndEnumFilters
    06706                 }
    06707         }
    06708
    06709         if(m_fShockwaveGraph)
    06710         {
    06711                 m_fAudioOnly = false;
    06712         }
    06713
    06714         if(!m_pCAP)
    06715         {
    06716                 pVW->put_Owner((OAHWND)m_wndView.m_hWnd);
    06717                 pVW->put_WindowStyle(WS_CHILD|WS_CLIPSIBLINGS|WS_CLIPCHILDREN);
    06718                 pVW->put_MessageDrain((OAHWND)m_hWnd);
    06719
    06720                 for(CWnd* pWnd = m_wndView.GetWindow(GW_CHILD); pWnd; pWnd = pWnd->GetNextWindow())
    06721                         pWnd->EnableWindow(FALSE); // little trick to let WM_SETCURSOR thru
    06722         }
    06723         else
    06724         {
    06725 return;
    06726 /*              char pSrcData[] =
    06727                         "sampler s0 : register(s0);\r\n"
    06728                         "float4 p0 : register(c0);\r\n"
    06729                         "\r\n"
    06730                         "#define counter (p0[2])\r\n"
    06731                         "#define clock (p0[3])\r\n"
    06732                         "\r\n"
    06733                         "float4 main(float2 t0 : TEXCOORD0) : COLOR\r\n"
    06734                         "{\r\n"
    06735                         "\tfloat4 c0 = tex2D(s0, t0);\r\n"
    06736                         "\tfloat3 lightsrc = float3(sin(clock*3.1415/3000)/2+0.5,cos(clock*3.1415/1000)/2+0.5,1);\r\n"
    06737                         "\tfloat3 light = normalize(lightsrc - float3(t0.x,t0.y,0));\r\n"
    06738                         "\tc0 *= pow(dot(light, float3(0,0,1)), 10);\r\n"
    06739                         "\treturn c0;\r\n"
    06740                         "}\r\n";
    06741
    06742                 //CComPtr<ID3DXBuffer> pErrorMsgs;
    06743                 HRESULT hr = m_pCAP->SetPixelShader(pSrcData, "ps_2_0");
    06744                 if(FAILED(hr))
    06745                 {
    06746
    06747                         CStringA err;
    06748                         int len = pErrorMsgs->GetBufferSize();
    06749                         memcpy(err.GetBufferSetLength(len), pErrorMsgs->GetBufferPointer(), len);
    06750                         if(!err.IsEmpty()) AfxMessageBox(CString(err), MB_OK);
    06751                 }
    06752 */
    06753         }
    06754 }
    06755
    06756 void CMainFrame::OpenSetupAudio()
    06757 {
    06758         pBA->put_Volume(m_wndToolBar.Volume);
    06759
    06760         // FIXME
    06761         int balance = AfxGetAppSettings().nBalance;
    06762         int sign = balance>0?-1:1;
    06763         balance = max(100-abs(balance), 1);
    06764         balance = (int)((log10(1.0*balance)-2)*5000*sign);
    06765         balance = max(min(balance, 10000), -10000);
    06766         pBA->put_Balance(balance);
    06767 }
    06768 /*
    06769 void CMainFrame::OpenSetupToolBar()
    06770 {
    06771 //      m_wndToolBar.Volume = AfxGetAppSettings().nVolume;
    06772 //      SetBalance(AfxGetAppSettings().nBalance);
    06773 }
    06774 */
    06775 void CMainFrame::OpenSetupCaptureBar()
    06776 {
    06777         if(m_iPlaybackMode == PM_CAPTURE)
    06778         {
    06779                 if(pVidCap && pAMVSCCap)
    06780                 {
    06781             CComQIPtr<IAMVfwCaptureDialogs> pVfwCD = pVidCap;
    06782
    06783                         if(!pAMXBar && pVfwCD)
    06784                         {
    06785                                 m_wndCaptureBar.m_capdlg.SetupVideoControls(m_VidDispName, pAMVSCCap, pVfwCD);
    06786                         }
    06787                         else
    06788                         {
    06789                                 m_wndCaptureBar.m_capdlg.SetupVideoControls(m_VidDispName, pAMVSCCap, pAMXBar, pAMTuner);
    06790                         }
    06791                 }
    06792
    06793                 if(pAudCap && pAMASC)
    06794                 {
    06795                         CInterfaceArray<IAMAudioInputMixer> pAMAIM;
    06796
    06797                         BeginEnumPins(pAudCap, pEP, pPin)
    06798                         {
    06799                                 PIN_DIRECTION dir;
    06800                                 if(FAILED(pPin->QueryDirection(&dir)) || dir != PINDIR_INPUT)
    06801                                         continue;
    06802
    06803                                 if(CComQIPtr<IAMAudioInputMixer> pAIM = pPin)
    06804                                         pAMAIM.Add(pAIM);
    06805                         }
    06806                         EndEnumPins
    06807
    06808                         m_wndCaptureBar.m_capdlg.SetupAudioControls(m_AudDispName, pAMASC, pAMAIM);
    06809                 }
    06810         }
    06811
    06812         BuildGraphVideoAudio(
    06813                 !!m_wndCaptureBar.m_capdlg.m_fVidPreview, false,
    06814                 !!m_wndCaptureBar.m_capdlg.m_fAudPreview, false);
    06815 }
    06816
    06817 void CMainFrame::OpenSetupInfoBar()
    06818 {
    06819         if(m_iPlaybackMode == PM_FILE)
    06820         {
    06821                 bool fEmpty = true;
    06822                 BeginEnumFilters(pGB, pEF, pBF)
    06823                 {
    06824                         if(CComQIPtr<IAMMediaContent, &IID_IAMMediaContent> pAMMC = pBF)
    06825                         {
    06826                                 CComBSTR bstr;
    06827                                 if(SUCCEEDED(pAMMC->get_Title(&bstr))) {m_wndInfoBar.SetLine(_T("Title"), bstr.m_str); if(bstr.Length()) fEmpty = false;}
    06828                                 if(SUCCEEDED(pAMMC->get_AuthorName(&bstr))) {m_wndInfoBar.SetLine(_T("Author"), bstr.m_str); if(bstr.Length()) fEmpty = false;}
    06829                                 if(SUCCEEDED(pAMMC->get_Copyright(&bstr))) {m_wndInfoBar.SetLine(_T("Copyright"), bstr.m_str); if(bstr.Length()) fEmpty = false;}
    06830                                 if(SUCCEEDED(pAMMC->get_Rating(&bstr))) {m_wndInfoBar.SetLine(_T("Rating"), bstr.m_str); if(bstr.Length()) fEmpty = false;}
    06831                                 if(SUCCEEDED(pAMMC->get_Description(&bstr))) {m_wndInfoBar.SetLine(_T("Description"), bstr.m_str); if(bstr.Length()) fEmpty = false;}
    06832                                 if(!fEmpty)
    06833                                 {
    06834                                         RecalcLayout();
    06835                                         break;
    06836                                 }
    06837                         }
    06838                 }
    06839                 EndEnumFilters
    06840         }
    06841         else if(m_iPlaybackMode == PM_DVD)
    06842         {
    06843                 CString info('-');
    06844                 m_wndInfoBar.SetLine(_T("Domain"), info);
    06845                 m_wndInfoBar.SetLine(_T("Location"), info);
    06846                 m_wndInfoBar.SetLine(_T("Video"), info);
    06847                 m_wndInfoBar.SetLine(_T("Audio"), info);
    06848                 m_wndInfoBar.SetLine(_T("Subtitles"), info);
    06849                 RecalcLayout();
    06850         }
    06851 }
    06852
    06853 void CMainFrame::OpenSetupStatsBar()
    06854 {
    06855         CString info('-');
    06856
    06857         BeginEnumFilters(pGB, pEF, pBF)
    06858         {
    06859                 if(!pQP && (pQP = pBF))
    06860                 {
    06861                         m_wndStatsBar.SetLine(_T("Frame-rate"), info);
    06862                         m_wndStatsBar.SetLine(_T("Sync Offset"), info);
    06863                         m_wndStatsBar.SetLine(_T("Frames"), info);
    06864                         m_wndStatsBar.SetLine(_T("Jitter"), info);
    06865                         m_wndStatsBar.SetLine(_T("Buffers"), info);
    06866                         m_wndStatsBar.SetLine(_T("Bitrate"), info);
    06867                         RecalcLayout();
    06868                 }
    06869
    06870                 if(!pBI && (pBI = pBF))
    06871                 {
    06872                         m_wndStatsBar.SetLine(_T("Buffers"), info);
    06873                         m_wndStatsBar.SetLine(_T("Bitrate"), info); // FIXME: shouldn't be here
    06874                         RecalcLayout();
    06875                 }
    06876         }
    06877         EndEnumFilters
    06878 }
    06879
    06880 void CMainFrame::OpenSetupStatusBar()
    06881 {
    06882         m_wndStatusBar.ShowTimer(true);
    06883
    06884         //
    06885
    06886         if(!m_fCustomGraph)
    06887         {
    06888                 UINT id = IDB_NOAUDIO;
    06889
    06890                 BeginEnumFilters(pGB, pEF, pBF)
    06891                 {
    06892                         CComQIPtr<IBasicAudio> pBA = pBF;
    06893                         if(!pBA) continue;
    06894
    06895                         BeginEnumPins(pBF, pEP, pPin)
    06896                         {
    06897                                 PIN_DIRECTION dir;
    06898                                 CComPtr<IPin> pPinTo;
    06899                                 if(S_OK == pPin->QueryDirection(&dir) && dir == PINDIR_INPUT
    06900                                 && S_OK == pPin->ConnectedTo(&pPinTo) && pPinTo)
    06901                                 {
    06902                                         AM_MEDIA_TYPE mt;
    06903                                         memset(&mt, 0, sizeof(mt));
    06904                                         pPin->ConnectionMediaType(&mt);
    06905
    06906                                         if(mt.majortype == MEDIATYPE_Audio
    06907                                         && mt.formattype == FORMAT_WaveFormatEx)
    06908                                         {
    06909                                                 switch(((WAVEFORMATEX*)mt.pbFormat)->nChannels)
    06910                                                 {
    06911                                                 case 1: id = IDB_MONO; break;
    06912                                                 case 2: default: id = IDB_STEREO; break;
    06913                                                 }
    06914                                                 break;
    06915                                         }
    06916                                         else if(mt.majortype == MEDIATYPE_Midi)
    06917                                         {
    06918                                                 id = NULL;
    06919                                                 break;
    06920                                         }
    06921                                 }
    06922                         }
    06923                         EndEnumPins
    06924
    06925                         if(id != IDB_NOAUDIO)
    06926                         {
    06927                                 break;
    06928                         }
    06929                 }
    06930                 EndEnumFilters
    06931
    06932                 m_wndStatusBar.SetStatusBitmap(id);
    06933         }
    06934
    06935         //
    06936
    06937         HICON hIcon = NULL;
    06938
    06939         if(m_iPlaybackMode == PM_FILE)
    06940         {
    06941                 CString fn = m_wndPlaylistBar.GetCur();
    06942                 CString ext = fn.Mid(fn.ReverseFind('.')+1);
    06943                 hIcon = LoadIcon(ext, true);
    06944         }
    06945         else if(m_iPlaybackMode == PM_DVD)
    06946         {
    06947                 hIcon = LoadIcon(_T(".ifo"), true);
    06948         }
    06949         else if(m_iPlaybackMode == PM_DVD)
    06950         {
    06951                 // hIcon = ; // TODO
    06952         }
    06953
    06954         m_wndStatusBar.SetStatusTypeIcon(hIcon);
    06955 }
    06956
    06957 void CMainFrame::OpenSetupWindowTitle(CString fn)
    06958 {
    06959         CString title(MAKEINTRESOURCE(IDR_MAINFRAME));
    06960
    06961         int i = AfxGetAppSettings().iTitleBarTextStyle;
    06962
    06963         if(!fn.IsEmpty() && (i == 0 || i == 1))
    06964         {
    06965                 if(i == 1)
    06966                 {
    06967                         if(m_iPlaybackMode == PM_FILE)
    06968                         {
    06969                                 fn.Replace('\\', '/');
    06970                                 CString fn2 = fn.Mid(fn.ReverseFind('/')+1);
    06971                                 if(!fn2.IsEmpty()) fn = fn2;
    06972                         }
    06973                         else if(m_iPlaybackMode == PM_DVD)
    06974                         {
    06975                                 fn = _T("DVD");
    06976                         }
    06977                         else if(m_iPlaybackMode == PM_CAPTURE)
    06978                         {
    06979                                 fn = _T("Live");
    06980                         }
    06981                 }
    06982
    06983                 title = fn + _T(" - ") + title;
    06984         }
    06985
    06986         SetWindowText(title);
    06987 }
    06988
    06989 bool CMainFrame::OpenMediaPrivate(CAutoPtr<OpenMediaData> pOMD)
    06990 {
    06991         if(m_iMediaLoadState != MLS_CLOSED)
    06992         {
    06993                 ASSERT(0);
    06994                 return(false);
    06995         }
    06996
    06997         if(!dynamic_cast<OpenFileData*>(pOMD.m_p)
    06998         && !dynamic_cast<OpenDVDData*>(pOMD.m_p)
    06999         && !dynamic_cast<OpenDeviceData*>(pOMD.m_p))
    07000         {
    07001                 ASSERT(0);
    07002                 return(false);
    07003         }
    07004
    07005         if(OpenFileData* pOFD = dynamic_cast<OpenFileData*>(pOMD.m_p))
    07006         {
    07007                 if(pOFD->fns.IsEmpty())
    07008                         return(false);
    07009
    07010                 CString fn = pOFD->fns.GetHead();
    07011
    07012                 int i = fn.Find(_T(":\\"));
    07013                 if(i > 0)
    07014                 {
    07015                         CString drive = fn.Left(i+2);
    07016                         UINT type = GetDriveType(drive);
    07017                         CList<CString> sl;
    07018                         if(type == DRIVE_REMOVABLE || type == DRIVE_CDROM && GetCDROMType(drive[0], sl) != CDROM_Audio)
    07019                         {
    07020                                 int ret = IDRETRY;
    07021                                 while(ret == IDRETRY)
    07022                                 {
    07023                                         WIN32_FIND_DATA findFileData;
    07024                                         HANDLE h = FindFirstFile(fn, &findFileData);
    07025                                         if(h != INVALID_HANDLE_VALUE)
    07026                                         {
    07027                                                 FindClose(h);
    07028                                                 ret = IDOK;
    07029                                         }
    07030                                         else
    07031                                         {
    07032                                                 CString msg;
    07033                                                 msg.Format(_T("%s was not found, please insert media containing this file."), fn);
    07034                                                 ret = AfxMessageBox(msg, MB_RETRYCANCEL);
    07035                                         }
    07036                                 }
    07037
    07038                                 if(ret != IDOK)
    07039                                         return(false);
    07040                         }
    07041                 }
    07042         }
    07043
    07044         m_iMediaLoadState = MLS_LOADING;
    07045
    07046         // FIXME: Don't show "Closed" initially
    07047         PostMessage(WM_KICKIDLE);
    07048
    07049         CString err, aborted(_T("Aborted"));
    07050
    07051         m_fUpdateInfoBar = false;
    07052
    07053         try
    07054         {
    07055                 if(m_fOpeningAborted) throw aborted;
    07056
    07057                 OpenCreateGraphObject(pOMD);
    07058 AddToRot(pGB, &m_dwRegister);
    07059
    07060                 if(m_fOpeningAborted) throw aborted;
    07061
    07062                 SetupIViAudReg();
    07063
    07064                 if(m_fOpeningAborted) throw aborted;
    07065
    07066                 if(OpenFileData* p = dynamic_cast<OpenFileData*>(pOMD.m_p))
    07067                 {
    07068                         OpenFile(p);
    07069                 }
    07070                 else if(OpenDVDData* p = dynamic_cast<OpenDVDData*>(pOMD.m_p))
    07071                 {
    07072                         OpenDVD(p);
    07073                 }
    07074                 else if(OpenDeviceData* p = dynamic_cast<OpenDeviceData*>(pOMD.m_p))
    07075                 {
    07076                         OpenCapture(p);
    07077                 }
    07078                 else
    07079                 {
    07080                         throw _T("Can't open, invalid input parameters");
    07081                 }
    07082
    07083                 if(m_fOpeningAborted) throw aborted;
    07084
    07085                 OpenCustomizeGraph();
    07086
    07087                 if(m_fOpeningAborted) throw aborted;
    07088
    07089                 OpenSetupVideo();
    07090
    07091                 if(m_fOpeningAborted) throw aborted;
    07092
    07093                 OpenSetupAudio();
    07094
    07095                 if(m_fOpeningAborted) throw aborted;
    07096
    07097                 if(m_pCAP && (!m_fAudioOnly || m_fRealMediaGraph))
    07098                 {
    07099                         POSITION pos = pOMD->subs.GetHeadPosition();
    07100                         while(pos) LoadSubtitle(pOMD->subs.GetNext(pos));
    07101
    07102                         if(m_pSubStreams.GetCount() > 0)
    07103                                 SetSubtitle(m_pSubStreams.GetHead());
    07104                 }
    07105
    07106                 if(m_fOpeningAborted) throw aborted;
    07107
    07108                 OpenSetupWindowTitle(pOMD->title);
    07109
    07110                 if(::GetCurrentThreadId() == AfxGetApp()->m_nThreadID)
    07111                 {
    07112                         OnFilePostOpenmedia();
    07113                 }
    07114                 else
    07115                 {
    07116                         PostMessage(WM_COMMAND, ID_FILE_POST_OPENMEDIA);
    07117                 }
    07118
    07119                 while(m_iMediaLoadState != MLS_LOADED
    07120                         && m_iMediaLoadState != MLS_CLOSING // FIXME
    07121                         )
    07122                 {
    07123                         Sleep(50);
    07124                 }
    07125
    07126                 // PostMessage instead of SendMessage because the user might call CloseMedia and then we would deadlock
    07127
    07128                 PostMessage(WM_COMMAND, ID_PLAY_PAUSE);
    07129
    07130                 if(!(AfxGetAppSettings().nCLSwitches&CLSW_OPEN))
    07131                         PostMessage(WM_COMMAND, ID_PLAY_PLAY);
    07132
    07133                 AfxGetAppSettings().nCLSwitches &= ~CLSW_OPEN;
    07134
    07135                 if(OpenFileData* p = dynamic_cast<OpenFileData*>(pOMD.m_p))
    07136                 {
    07137                         if(p->rtStart > 0)
    07138                                 PostMessage(WM_RESUMEFROMSTATE, (WPARAM)PM_FILE, (LPARAM)(p->rtStart/10000)); // REFERENCE_TIME doesn't fit in LPARAM under a 32bit env.
    07139                 }
    07140                 else if(OpenDVDData* p = dynamic_cast<OpenDVDData*>(pOMD.m_p))
    07141                 {
    07142                         if(p->pDvdState)
    07143                                 PostMessage(WM_RESUMEFROMSTATE, (WPARAM)PM_DVD, (LPARAM)(CComPtr<IDvdState>(p->pDvdState).Detach())); // must be released by the called message handler
    07144                 }
    07145                 else if(OpenDeviceData* p = dynamic_cast<OpenDeviceData*>(pOMD.m_p))
    07146                 {
    07147                         m_wndCaptureBar.m_capdlg.SetVideoInput(p->vinput);
    07148                         m_wndCaptureBar.m_capdlg.SetVideoChannel(p->vchannel);
    07149                         m_wndCaptureBar.m_capdlg.SetAudioInput(p->ainput);
    07150                 }
    07151         }
    07152         catch(LPCTSTR msg)
    07153         {
    07154                 err = msg;
    07155         }
    07156         catch(CString msg)
    07157         {
    07158                 err = msg;
    07159         }
    07160
    07161         if(!err.IsEmpty())
    07162         {
    07163                 CloseMediaPrivate();
    07164                 m_closingmsg = err;
    07165
    07166                 OpenFileData* p = dynamic_cast<OpenFileData*>(pOMD.m_p);
    07167                 if(p && err != aborted)
    07168                 {
    07169                         m_wndPlaylistBar.SetCurValid(false);
    07170                         if(m_wndPlaylistBar.GetCount() > 1)
    07171                         {
    07172                                 CPlaylistItem pli[2];
    07173                                 m_wndPlaylistBar.GetCur(pli[0]);
    07174                                 m_wndPlaylistBar.SetNext();
    07175                                 m_wndPlaylistBar.GetCur(pli[1]);
    07176                                 if(pli[0].m_id != pli[1].m_id)
    07177                                 {
    07178                                         CAutoPtr<OpenMediaData> p(m_wndPlaylistBar.GetCurOMD());
    07179                                         if(p) OpenMediaPrivate(p);
    07180                                 }
    07181                         }
    07182                 }
    07183         }
    07184         else
    07185         {
    07186                 m_wndPlaylistBar.SetCurValid(true);
    07187         }
    07188
    07189         PostMessage(WM_KICKIDLE); // calls main thread to update things
    07190
    07191         return(err.IsEmpty());
    07192 }
    07193
    07194 void CMainFrame::CloseMediaPrivate()
    07195 {
    07196         m_iMediaLoadState = MLS_CLOSING;
    07197
    07198     OnPlayStop(); // SendMessage(WM_COMMAND, ID_PLAY_STOP);
    07199
    07200         m_iPlaybackMode = PM_NONE;
    07201         m_iSpeedLevel = 0;
    07202
    07203         m_fLiveWM = false;
    07204
    07205         m_fEndOfStream = false;
    07206
    07207         m_rtDurationOverride = -1;
    07208
    07209         m_kfs.RemoveAll();
    07210
    07211         m_pCB = NULL;
    07212
    07213 RemoveFromRot(m_dwRegister);
    07214
    07215 //      if(pVW) pVW->put_Visible(OAFALSE);
    07216 //      if(pVW) pVW->put_MessageDrain((OAHWND)NULL), pVW->put_Owner((OAHWND)NULL);
    07217
    07218         m_pCAP = NULL; // IMPORTANT: IVMRSurfaceAllocatorNotify/IVMRSurfaceAllocatorNotify9 has to be released before the VMR/VMR9, otherwise it will crash in Release()
    07219         m_shaderlabel.Empty();
    07220
    07221         pAMXBar.Release(); pAMTuner.Release(); pAMDF.Release();
    07222         pAMVCCap.Release(); pAMVCPrev.Release(); pAMVSCCap.Release(); pAMVSCPrev.Release(); pAMASC.Release();
    07223         pVidCap.Release(); pAudCap.Release();
    07224         pCGB.Release();
    07225         pVMR.Release();
    07226         pDVDC.Release(); pDVDI.Release();
    07227         pQP.Release(); pBI.Release(); pAMOP.Release(); pFS.Release();
    07228         pMC.Release(); pME.Release(); pMS.Release();
    07229         pVW.Release(); pBV.Release();
    07230         pBA.Release();
    07231         pGB.Release();
    07232
    07233         m_fRealMediaGraph = m_fShockwaveGraph = m_fQuicktimeGraph = false;
    07234
    07235         m_pSubClock = NULL;
    07236
    07237         m_pProv.Release();
    07238
    07239         {
    07240                 CAutoLock cAutoLock(&m_csSubLock);
    07241                 m_pSubStreams.RemoveAll();
    07242         }
    07243
    07244         m_VidDispName.Empty();
    07245         m_AudDispName.Empty();
    07246
    07247         m_closingmsg = _T("Closed");
    07248
    07249         AfxGetAppSettings().nCLSwitches &= CLSW_OPEN|CLSW_PLAY|CLSW_AFTERPLAYBACK_MASK|CLSW_NOFOCUS;
    07250
    07251         m_iMediaLoadState = MLS_CLOSED;
    07252 }
    07253
    07254 // msn
    07255
    07256 void CMainFrame::SendNowPlayingToMSN()
    07257 {
    07258         if(!AfxGetAppSettings().fNotifyMSN)
    07259                 return;
    07260
    07261         CString title, author;
    07262
    07263         if(m_iMediaLoadState == MLS_LOADED)
    07264         {
    07265                 m_wndInfoBar.GetLine(_T("Title"), title);
    07266                 m_wndInfoBar.GetLine(_T("Author"), author);
    07267
    07268                 if(title.IsEmpty())
    07269                 {
    07270                         CPlaylistItem pli;
    07271                         m_wndPlaylistBar.GetCur(pli);
    07272
    07273                         if(!pli.m_fns.IsEmpty())
    07274                         {
    07275                                 CString label = !pli.m_label.IsEmpty() ? pli.m_label : pli.m_fns.GetHead();
    07276
    07277                                 if(m_iPlaybackMode == PM_FILE)
    07278                                 {
    07279                                         CString fn = label;
    07280                                         if(fn.Find(_T("://")) >= 0) {int i = fn.Find('?'); if(i >= 0) fn = fn.Left(i);}
    07281                                         CPath path(fn);
    07282                                         path.StripPath();
    07283                                         path.MakePretty();
    07284                                         path.RemoveExtension();
    07285                                         title = (LPCTSTR)path;
    07286                                         author.Empty();
    07287                                 }
    07288                                 else if(m_iPlaybackMode == PM_CAPTURE)
    07289                                 {
    07290                                         title = label != pli.m_fns.GetHead() ? label : _T("Live");
    07291                                         author.Empty();
    07292                                 }
    07293                                 else if(m_iPlaybackMode == PM_DVD)
    07294                                 {
    07295                                         title = _T("DVD");
    07296                                         author.Empty();
    07297                                 }
    07298                         }
    07299                 }
    07300         }
    07301
    07302         CStringW buff;
    07303         buff += L"\\0Music\\0";
    07304         buff += title.IsEmpty() ? L"0" : L"1";
    07305         buff += L"\\0";
    07306         buff += author.IsEmpty() ? L"{0}" : L"{0} - {1}";
    07307         buff += L"\\0";
    07308         if(!author.IsEmpty()) {buff += CStringW(author) + L"\\0";}
    07309         buff += CStringW(title) + L"\\0";
    07310         buff += L"\\0\\0";
    07311
    07312         COPYDATASTRUCT data;
    07313     data.dwData = 0x0547;
    07314     data.lpData = (PVOID)(LPCWSTR)buff;
    07315     data.cbData = buff.GetLength() * 2 + 2;
    07316
    07317         HWND hWnd = NULL;
    07318         while(hWnd = ::FindWindowEx(NULL, hWnd, _T("MsnMsgrUIManager"), NULL))
    07319                 ::SendMessage(hWnd, WM_COPYDATA, (WPARAM)NULL, (LPARAM)&data);
    07320 }
    07321
    07322 // dynamic menus
    07323
    07324 void CMainFrame::SetupOpenCDSubMenu()
    07325 {
    07326         CMenu* pSub = &m_opencds;
    07327
    07328         if(!IsMenu(pSub->m_hMenu)) pSub->CreatePopupMenu();
    07329         else while(pSub->RemoveMenu(0, MF_BYPOSITION));
    07330
    07331         if(m_iMediaLoadState == MLS_LOADING) return;
    07332
    07333         if(AfxGetAppSettings().fHideCDROMsSubMenu) return;
    07334
    07335         UINT id = ID_FILE_OPEN_CD_START;
    07336
    07337         for(TCHAR drive = 'C'; drive <= 'Z'; drive++)
    07338         {
    07339                 CString label = GetDriveLabel(drive), str;
    07340
    07341                 CList<CString> files;
    07342                 switch(GetCDROMType(drive, files))
    07343                 {
    07344                 case CDROM_Audio:
    07345                         if(label.IsEmpty()) label = _T("Audio CD");
    07346                         str.Format(_T("%s (%c:)"), label, drive);
    07347                         break;
    07348                 case CDROM_VideoCD:
    07349                         if(label.IsEmpty()) label = _T("(S)VCD");
    07350                         str.Format(_T("%s (%c:)"), label, drive);
    07351                         break;
    07352                 case CDROM_DVDVideo:
    07353                         if(label.IsEmpty()) label = _T("DVD Video");
    07354                         str.Format(_T("%s (%c:)"), label, drive);
    07355                         break;
    07356                 default:
    07357                         break;
    07358                 }
    07359
    07360                 if(!str.IsEmpty())
    07361                         pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, str);
    07362         }
    07363 }
    07364
    07365 void CMainFrame::SetupFiltersSubMenu()
    07366 {
    07367         CMenu* pSub = &m_filters;
    07368
    07369         if(!IsMenu(pSub->m_hMenu)) pSub->CreatePopupMenu();
    07370         else while(pSub->RemoveMenu(0, MF_BYPOSITION));
    07371
    07372         m_filterpopups.RemoveAll();
    07373
    07374         m_spparray.RemoveAll();
    07375         m_ssarray.RemoveAll();
    07376
    07377         if(m_iMediaLoadState == MLS_LOADED)
    07378         {
    07379                 UINT idf = 0;
    07380                 UINT ids = ID_FILTERS_SUBITEM_START;
    07381                 UINT idl = ID_FILTERSTREAMS_SUBITEM_START;
    07382
    07383                 BeginEnumFilters(pGB, pEF, pBF)
    07384                 {
    07385                         CString name(GetFilterName(pBF));
    07386                         if(name.GetLength() >= 43) name = name.Left(40) + _T("...");
    07387
    07388                         CLSID clsid = GetCLSID(pBF);
    07389                         if(clsid == CLSID_AVIDec)
    07390                         {
    07391                                 CComPtr<IPin> pPin = GetFirstPin(pBF);
    07392                                 AM_MEDIA_TYPE mt;
    07393                                 if(pPin && SUCCEEDED(pPin->ConnectionMediaType(&mt)))
    07394                                 {
    07395                                         DWORD c = ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biCompression;
    07396                                         switch(c)
    07397                                         {
    07398                                         case BI_RGB: name += _T(" (RGB)"); break;
    07399                                         case BI_RLE4: name += _T(" (RLE4)"); break;
    07400                                         case BI_RLE8: name += _T(" (RLE8)"); break;
    07401                                         case BI_BITFIELDS: name += _T(" (BITF)"); break;
    07402                                         default: name.Format(_T("%s (%c%c%c%c)"),
    07403                                                                  CString(name), (TCHAR)((c>>0)&0xff), (TCHAR)((c>>8)&0xff), (TCHAR)((c>>16)&0xff), (TCHAR)((c>>24)&0xff)); break;
    07404                                         }
    07405                                 }
    07406                         }
    07407                         else if(clsid == CLSID_ACMWrapper)
    07408                         {
    07409                                 CComPtr<IPin> pPin = GetFirstPin(pBF);
    07410                                 AM_MEDIA_TYPE mt;
    07411                                 if(pPin && SUCCEEDED(pPin->ConnectionMediaType(&mt)))
    07412                                 {
    07413                                         WORD c = ((WAVEFORMATEX*)mt.pbFormat)->wFormatTag;
    07414                                         name.Format(_T("%s (0x%04x)"), CString(name), (int)c);
    07415                                 }
    07416                         }
    07417                         else if(clsid == __uuidof(CTextPassThruFilter) || clsid == __uuidof(CNullTextRenderer)
    07418                                 || clsid == GUIDFromCString(_T("{48025243-2D39-11CE-875D-00608CB78066}"))) // ISCR
    07419                         {
    07420                                 // hide these
    07421                                 continue;
    07422                         }
    07423
    07424                         CAutoPtr<CMenu> pSubSub(new CMenu);
    07425                         pSubSub->CreatePopupMenu();
    07426
    07427                         int nPPages = 0;
    07428
    07429                         CComQIPtr<ISpecifyPropertyPages> pSPP = pBF;
    07430                         if(pSPP)
    07431                         {
    07432                                 CAUUID caGUID;
    07433                                 caGUID.pElems = NULL;
    07434                                 if(SUCCEEDED(pSPP->GetPages(&caGUID)) && caGUID.cElems > 0)
    07435                                 {
    07436                                         m_spparray.Add(pSPP);
    07437                                         pSubSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, ids, _T("&Properties..."));
    07438
    07439                                         if(caGUID.pElems) CoTaskMemFree(caGUID.pElems);
    07440
    07441                                         nPPages++;
    07442                                 }
    07443                         }
    07444
    07445                         BeginEnumPins(pBF, pEP, pPin)
    07446                         {
    07447                                 CString name = GetPinName(pPin);
    07448                                 name.Replace(_T("&"), _T("&&"));
    07449
    07450                                 if(pSPP = pPin)
    07451                                 {
    07452                                         CAUUID caGUID;
    07453                                         caGUID.pElems = NULL;
    07454                                         if(SUCCEEDED(pSPP->GetPages(&caGUID)) && caGUID.cElems > 0)
    07455                                         {
    07456                                                 m_spparray.Add(pSPP);
    07457                                                 pSubSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, ids+nPPages, name + _T(" (pin) properties..."));
    07458
    07459                                                 if(caGUID.pElems) CoTaskMemFree(caGUID.pElems);
    07460
    07461                                                 nPPages++;
    07462                                         }
    07463                                 }
    07464                         }
    07465                         EndEnumPins
    07466
    07467                         CComQIPtr<IAMStreamSelect> pSS = pBF;
    07468                         if(pSS)
    07469                         {
    07470                                 DWORD nStreams = 0, flags, group, prevgroup = -1;
    07471                                 LCID lcid;
    07472                                 WCHAR* wname = NULL;
    07473                                 CComPtr<IUnknown> pObj, pUnk;
    07474
    07475                                 pSS->Count(&nStreams);
    07476
    07477                                 if(nStreams > 0 && nPPages > 0) pSubSub->AppendMenu(MF_SEPARATOR|MF_ENABLED);
    07478
    07479                                 UINT idlstart = idl;
    07480
    07481                                 for(DWORD i = 0; i < nStreams; i++, pObj = NULL, pUnk = NULL)
    07482                                 {
    07483                                         m_ssarray.Add(pSS);
    07484
    07485                                         flags = group = 0;
    07486                                         wname = NULL;
    07487                                         pSS->Info(i, NULL, &flags, &lcid, &group, &wname, &pObj, &pUnk);
    07488
    07489                                         if(group != prevgroup && idl > idlstart)
    07490                                                 pSubSub->AppendMenu(MF_SEPARATOR|MF_ENABLED);
    07491                                         prevgroup = group;
    07492
    07493                                         if(flags & AMSTREAMSELECTINFO_EXCLUSIVE)
    07494                                         {
    07495                                         }
    07496                                         else if(flags & AMSTREAMSELECTINFO_ENABLED)
    07497                                         {
    07498                                         }
    07499
    07500                                         if(!wname)
    07501                                         {
    07502                                                 CStringW stream(L"Unknown Stream");
    07503                                                 wname = (WCHAR*)CoTaskMemAlloc((stream.GetLength()+3+1)*sizeof(WCHAR));
    07504                                                 swprintf(wname, L"%s %d", stream, min(i+1,999));
    07505                                         }
    07506
    07507                                         CString name(wname);
    07508                                         name.Replace(_T("&"), _T("&&"));
    07509
    07510                                         pSubSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, idl++, name);
    07511
    07512                                         CoTaskMemFree(wname);
    07513                                 }
    07514
    07515                                 if(nStreams == 0) pSS.Release();
    07516                         }
    07517
    07518                         if(nPPages == 1 && !pSS)
    07519                         {
    07520                                 pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, ids, name);
    07521                         }
    07522                         else
    07523                         {
    07524                                 pSub->AppendMenu(MF_BYPOSITION|MF_STRING|MF_DISABLED|MF_GRAYED, idf, name);
    07525
    07526                                 if(nPPages > 0 || pSS)
    07527                                 {
    07528                                         MENUITEMINFO mii;
    07529                                         mii.cbSize = sizeof(mii);
    07530                                         mii.fMask = MIIM_STATE|MIIM_SUBMENU;
    07531                                         mii.fType = MF_POPUP;
    07532                                         mii.hSubMenu = pSubSub->m_hMenu;
    07533                                         mii.fState = (pSPP || pSS) ? MF_ENABLED : (MF_DISABLED|MF_GRAYED);
    07534                                         pSub->SetMenuItemInfo(idf, &mii, TRUE);
    07535
    07536                                         m_filterpopups.Add(pSubSub);
    07537                                 }
    07538                         }
    07539
    07540                         ids += nPPages;
    07541                         idf++;
    07542                 }
    07543                 EndEnumFilters
    07544         }
    07545 }
    07546
    07547 void CMainFrame::SetupAudioSwitcherSubMenu()
    07548 {
    07549         CMenu* pSub = &m_audios;
    07550
    07551         if(!IsMenu(pSub->m_hMenu)) pSub->CreatePopupMenu();
    07552         else while(pSub->RemoveMenu(0, MF_BYPOSITION));
    07553
    07554         if(m_iMediaLoadState == MLS_LOADED)
    07555         {
    07556                 UINT id = ID_AUDIO_SUBITEM_START;
    07557
    07558                 CComQIPtr<IAMStreamSelect> pSS = FindFilter(__uuidof(CAudioSwitcherFilter), pGB);
    07559                 if(!pSS) pSS = FindFilter(L"{D3CD7858-971A-4838-ACEC-40CA5D529DC8}", pGB);
    07560
    07561                 if(pSS)
    07562                 {
    07563                         DWORD cStreams = 0;
    07564                         if(SUCCEEDED(pSS->Count(&cStreams)) && cStreams > 0)
    07565                         {
    07566                                 pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, _T("&Options..."));
    07567                                 pSub->AppendMenu(MF_SEPARATOR|MF_ENABLED);
    07568
    07569                                 for(int i = 0; i < (int)cStreams; i++)
    07570                                 {
    07571                                         WCHAR* pName = NULL;
    07572                                         if(FAILED(pSS->Info(i, NULL, NULL, NULL, NULL, &pName, NULL, NULL)))
    07573                                                 break;
    07574
    07575                                         CString name(pName);
    07576                                         name.Replace(_T("&"), _T("&&"));
    07577
    07578                                         pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, name);
    07579
    07580                                         CoTaskMemFree(pName);
    07581                                 }
    07582                         }
    07583                 }
    07584         }
    07585 }
    07586
    07587 void CMainFrame::SetupSubtitlesSubMenu()
    07588 {
    07589         CMenu* pSub = &m_subtitles;
    07590
    07591         if(!IsMenu(pSub->m_hMenu)) pSub->CreatePopupMenu();
    07592         else while(pSub->RemoveMenu(0, MF_BYPOSITION));
    07593
    07594         if(m_iMediaLoadState != MLS_LOADED || m_fAudioOnly || !m_pCAP)
    07595                 return;
    07596
    07597         UINT id = ID_SUBTITLES_SUBITEM_START;
    07598
    07599         POSITION pos = m_pSubStreams.GetHeadPosition();
    07600
    07601         if(pos)
    07602         {
    07603                 pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, _T("&Options..."));
    07604                 pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, _T("&Styles..."));
    07605                 pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, _T("&Reload"));
    07606                 pSub->AppendMenu(MF_SEPARATOR);
    07607
    07608                 pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, _T("&Enable"));
    07609                 pSub->AppendMenu(MF_SEPARATOR);
    07610         }
    07611
    07612         while(pos)
    07613         {
    07614                 CComPtr<ISubStream> pSubStream = m_pSubStreams.GetNext(pos);
    07615                 if(!pSubStream) continue;
    07616
    07617                 for(int i = 0, j = pSubStream->GetStreamCount(); i < j; i++)
    07618                 {
    07619                         WCHAR* pName = NULL;
    07620                         if(SUCCEEDED(pSubStream->GetStreamInfo(i, &pName, NULL)))
    07621                         {
    07622                                 CString name(pName);
    07623                                 name.Replace(_T("&"), _T("&&"));
    07624
    07625                                 pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, name);
    07626                                 CoTaskMemFree(pName);
    07627                         }
    07628                         else
    07629                         {
    07630                                 pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, _T("<Unknown>"));
    07631                         }
    07632                 }
    07633
    07634                 // TODO: find a better way to group these entries
    07635                 if(pos && m_pSubStreams.GetAt(pos))
    07636                 {
    07637                         CLSID cur, next;
    07638                         pSubStream->GetClassID(&cur);
    07639                         m_pSubStreams.GetAt(pos)->GetClassID(&next);
    07640
    07641                         if(cur != next)
    07642                                 pSub->AppendMenu(MF_SEPARATOR);
    07643                 }
    07644         }
    07645 }
    07646
    07647 void CMainFrame::SetupNavAudioSubMenu()
    07648 {
    07649         CMenu* pSub = &m_navaudio;
    07650
    07651         if(!IsMenu(pSub->m_hMenu)) pSub->CreatePopupMenu();
    07652         else while(pSub->RemoveMenu(0, MF_BYPOSITION));
    07653
    07654         if(m_iMediaLoadState != MLS_LOADED) return;
    07655
    07656         UINT id = ID_NAVIGATE_AUDIO_SUBITEM_START;
    07657
    07658         if(m_iPlaybackMode == PM_FILE)
    07659         {
    07660                 SetupNavStreamSelectSubMenu(pSub, id, 1);
    07661         }
    07662         else if(m_iPlaybackMode == PM_DVD)
    07663         {
    07664                 ULONG ulStreamsAvailable, ulCurrentStream;
    07665                 if(FAILED(pDVDI->GetCurrentAudio(&ulStreamsAvailable, &ulCurrentStream)))
    07666                         return;
    07667
    07668                 LCID DefLanguage;
    07669                 DVD_AUDIO_LANG_EXT ext;
    07670                 if(FAILED(pDVDI->GetDefaultAudioLanguage(&DefLanguage, &ext)))
    07671                         return;
    07672
    07673         for(ULONG i = 0; i < ulStreamsAvailable; i++)
    07674                 {
    07675                         LCID Language;
    07676                         if(FAILED(pDVDI->GetAudioLanguage(i, &Language)))
    07677                                 continue;
    07678
    07679                         UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
    07680                         if(Language == DefLanguage) flags |= MF_DEFAULT;
    07681             if(i == ulCurrentStream) flags |= MF_CHECKED;
    07682
    07683                         CString str(_T("Unknown"));
    07684                         if(Language)
    07685                         {
    07686                                 int len = GetLocaleInfo(Language, LOCALE_SENGLANGUAGE, str.GetBuffer(256), 256);
    07687                                 str.ReleaseBufferSetLength(max(len-1, 0));
    07688                         }
    07689
    07690                         DVD_AudioAttributes ATR;
    07691                         if(SUCCEEDED(pDVDI->GetAudioAttributes(i, &ATR)))
    07692                         {
    07693                                 switch(ATR.LanguageExtension)
    07694                                 {
    07695                                 case DVD_AUD_EXT_NotSpecified:
    07696                                 default: break;
    07697                                 case DVD_AUD_EXT_Captions: str += _T(" (Captions)"); break;
    07698                                 case DVD_AUD_EXT_VisuallyImpaired: str += _T(" (Visually Impaired)"); break;
    07699                                 case DVD_AUD_EXT_DirectorComments1: str += _T(" (Director Comments 1)"); break;
    07700                                 case DVD_AUD_EXT_DirectorComments2: str += _T(" (Director Comments 2)"); break;
    07701                                 }
    07702                         }
    07703
    07704                         str.Replace(_T("&"), _T("&&"));
    07705
    07706                         pSub->AppendMenu(flags, id++, str);
    07707                 }
    07708         }
    07709 }
    07710
    07711 void CMainFrame::SetupNavSubtitleSubMenu()
    07712 {
    07713         CMenu* pSub = &m_navsubtitle;
    07714
    07715         if(!IsMenu(pSub->m_hMenu)) pSub->CreatePopupMenu();
    07716         else while(pSub->RemoveMenu(0, MF_BYPOSITION));
    07717
    07718         if(m_iMediaLoadState != MLS_LOADED) return;
    07719
    07720         UINT id = ID_NAVIGATE_SUBP_SUBITEM_START;
    07721
    07722         if(m_iPlaybackMode == PM_FILE)
    07723         {
    07724                 SetupNavStreamSelectSubMenu(pSub, id, 2);
    07725         }
    07726         else if(m_iPlaybackMode == PM_DVD)
    07727         {
    07728                 ULONG ulStreamsAvailable, ulCurrentStream;
    07729                 BOOL bIsDisabled;
    07730                 if(FAILED(pDVDI->GetCurrentSubpicture(&ulStreamsAvailable, &ulCurrentStream, &bIsDisabled))
    07731                 || ulStreamsAvailable == 0)
    07732                         return;
    07733
    07734                 LCID DefLanguage;
    07735                 DVD_SUBPICTURE_LANG_EXT ext;
    07736                 if(FAILED(pDVDI->GetDefaultSubpictureLanguage(&DefLanguage, &ext)))
    07737                         return;
    07738
    07739                 pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|(bIsDisabled?0:MF_CHECKED), id++, _T("Enabled"));
    07740                 pSub->AppendMenu(MF_BYCOMMAND|MF_SEPARATOR|MF_ENABLED);
    07741
    07742         for(ULONG i = 0; i < ulStreamsAvailable; i++)
    07743                 {
    07744                         LCID Language;
    07745                         if(FAILED(pDVDI->GetSubpictureLanguage(i, &Language)))
    07746                                 continue;
    07747
    07748                         UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
    07749                         if(Language == DefLanguage) flags |= MF_DEFAULT;
    07750             if(i == ulCurrentStream) flags |= MF_CHECKED;
    07751
    07752                         CString str(_T("Unknown"));
    07753                         if(Language)
    07754                         {
    07755                                 int len = GetLocaleInfo(Language, LOCALE_SENGLANGUAGE, str.GetBuffer(256), 256);
    07756                                 str.ReleaseBufferSetLength(max(len-1, 0));
    07757                         }
    07758
    07759                         DVD_SubpictureAttributes ATR;
    07760                         if(SUCCEEDED(pDVDI->GetSubpictureAttributes(i, &ATR)))
    07761                         {
    07762                                 switch(ATR.LanguageExtension)
    07763                                 {
    07764                                 case DVD_SP_EXT_NotSpecified:
    07765                                 default: break;
    07766                                 case DVD_SP_EXT_Caption_Normal: str += _T(""); break;
    07767                                 case DVD_SP_EXT_Caption_Big: str += _T(" (Big)"); break;
    07768                                 case DVD_SP_EXT_Caption_Children: str += _T(" (Children)"); break;
    07769                                 case DVD_SP_EXT_CC_Normal: str += _T(" (CC)"); break;
    07770                                 case DVD_SP_EXT_CC_Big: str += _T(" (CC Big)"); break;
    07771                                 case DVD_SP_EXT_CC_Children: str += _T(" (CC Children)"); break;
    07772                                 case DVD_SP_EXT_Forced: str += _T(" (Forced)"); break;
    07773                                 case DVD_SP_EXT_DirectorComments_Normal: str += _T(" (Director Comments)"); break;
    07774                                 case DVD_SP_EXT_DirectorComments_Big: str += _T(" (Director Comments, Big)"); break;
    07775                                 case DVD_SP_EXT_DirectorComments_Children: str += _T(" (Director Comments, Children)"); break;
    07776                                 }
    07777                         }
    07778
    07779                         str.Replace(_T("&"), _T("&&"));
    07780
    07781                         pSub->AppendMenu(flags, id++, str);
    07782                 }
    07783         }
    07784 }
    07785
    07786 void CMainFrame::SetupNavAngleSubMenu()
    07787 {
    07788         CMenu* pSub = &m_navangle;
    07789
    07790         if(!IsMenu(pSub->m_hMenu)) pSub->CreatePopupMenu();
    07791         else while(pSub->RemoveMenu(0, MF_BYPOSITION));
    07792
    07793         if(m_iMediaLoadState != MLS_LOADED) return;
    07794
    07795         UINT id = ID_NAVIGATE_ANGLE_SUBITEM_START;
    07796
    07797         if(m_iPlaybackMode == PM_FILE)
    07798         {
    07799                 SetupNavStreamSelectSubMenu(pSub, id, 0);
    07800         }
    07801         else if(m_iPlaybackMode == PM_DVD)
    07802         {
    07803                 ULONG ulStreamsAvailable, ulCurrentStream;
    07804                 if(FAILED(pDVDI->GetCurrentAngle(&ulStreamsAvailable, &ulCurrentStream)))
    07805                         return;
    07806
    07807                 if(ulStreamsAvailable < 2) return; // one choice is not a choice...
    07808
    07809         for(ULONG i = 0; i < ulStreamsAvailable; i++)
    07810                 {
    07811                         UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
    07812             if(i == ulCurrentStream) flags |= MF_CHECKED;
    07813
    07814                         CString str;
    07815                         str.Format(_T("Angle %d"), i+1);
    07816
    07817                         pSub->AppendMenu(flags, id++, str);
    07818                 }
    07819         }
    07820 }
    07821
    07822 void CMainFrame::SetupNavChaptersSubMenu()
    07823 {
    07824         CMenu* pSub = &m_navchapters;
    07825
    07826         if(!IsMenu(pSub->m_hMenu)) pSub->CreatePopupMenu();
    07827         else while(pSub->RemoveMenu(0, MF_BYPOSITION));
    07828
    07829         if(m_iMediaLoadState != MLS_LOADED)
    07830                 return;
    07831
    07832         UINT id = ID_NAVIGATE_CHAP_SUBITEM_START;
    07833
    07834         if(m_iPlaybackMode == PM_FILE)
    07835         {
    07836                 SetupChapters();
    07837
    07838                 REFERENCE_TIME rt = GetPos();
    07839                 DWORD j = m_pCB->ChapLookup(&rt, NULL);
    07840
    07841                 for(DWORD i = 0; i < m_pCB->ChapGetCount(); i++, id++)
    07842                 {
    07843                         rt = 0;
    07844                         CComBSTR bstr;
    07845                         if(FAILED(m_pCB->ChapGet(i, &rt, &bstr)))
    07846                                 continue;
    07847
    07848                         int s = (int)((rt/10000000)%60);
    07849                         int m = (int)((rt/10000000/60)%60);
    07850                         int h = (int)((rt/10000000/60/60));
    07851
    07852                         CString time;
    07853                         time.Format(_T("[%02d:%02d:%02d] "), h, m, s);
    07854
    07855                         CString name = CString(bstr);
    07856                         name.Replace(_T("&"), _T("&&"));
    07857                         name.Replace(_T("\t"), _T(" "));
    07858
    07859                         UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
    07860                         if(i == j) flags |= MF_CHECKED;
    07861                         if(id != ID_NAVIGATE_CHAP_SUBITEM_START && i == 0) pSub->AppendMenu(MF_SEPARATOR);
    07862                         pSub->AppendMenu(flags, id, name + '\t' + time);
    07863                 }
    07864
    07865                 if(m_wndPlaylistBar.GetCount() > 1)
    07866                 {
    07867                         POSITION pos = m_wndPlaylistBar.m_pl.GetHeadPosition();
    07868                         while(pos)
    07869                         {
    07870                                 UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
    07871                                 if(pos == m_wndPlaylistBar.m_pl.GetPos()) flags |= MF_CHECKED;
    07872                                 if(id != ID_NAVIGATE_CHAP_SUBITEM_START && pos == m_wndPlaylistBar.m_pl.GetHeadPosition())
    07873                                         pSub->AppendMenu(MF_SEPARATOR);
    07874                                 CPlaylistItem& pli = m_wndPlaylistBar.m_pl.GetNext(pos);
    07875                                 CString name = pli.GetLabel();
    07876                                 name.Replace(_T("&"), _T("&&"));
    07877                                 pSub->AppendMenu(flags, id++, name);
    07878                         }
    07879                 }
    07880         }
    07881         else if(m_iPlaybackMode == PM_DVD)
    07882         {
    07883                 ULONG ulNumOfVolumes, ulVolume;
    07884                 DVD_DISC_SIDE Side;
    07885                 ULONG ulNumOfTitles = 0;
    07886                 pDVDI->GetDVDVolumeInfo(&ulNumOfVolumes, &ulVolume, &Side, &ulNumOfTitles);
    07887
    07888                 DVD_PLAYBACK_LOCATION2 Location;
    07889                 pDVDI->GetCurrentLocation(&Location);
    07890
    07891                 ULONG ulNumOfChapters = 0;
    07892                 pDVDI->GetNumberOfChapters(Location.TitleNum, &ulNumOfChapters);
    07893
    07894                 ULONG ulUOPs = 0;
    07895                 pDVDI->GetCurrentUOPS(&ulUOPs);
    07896
    07897                 for(ULONG i = 1; i <= ulNumOfTitles; i++)
    07898                 {
    07899                         UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
    07900                         if(i == Location.TitleNum) flags |= MF_CHECKED;
    07901                         if(ulUOPs&UOP_FLAG_Play_Title) flags |= MF_DISABLED|MF_GRAYED;
    07902
    07903                         CString str;
    07904                         str.Format(_T("Title %d"), i);
    07905
    07906                         pSub->AppendMenu(flags, id++, str);
    07907                 }
    07908
    07909                 for(ULONG i = 1; i <= ulNumOfChapters; i++)
    07910                 {
    07911                         UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
    07912                         if(i == Location.ChapterNum) flags |= MF_CHECKED;
    07913                         if(ulUOPs&UOP_FLAG_Play_Chapter) flags |= MF_DISABLED|MF_GRAYED;
    07914                         if(i == 1) flags |= MF_MENUBARBREAK;
    07915
    07916                         CString str;
    07917                         str.Format(_T("Chapter %d"), i);
    07918
    07919                         pSub->AppendMenu(flags, id++, str);
    07920                 }
    07921         }
    07922 }
    07923
    07924 void CMainFrame::SetupNavStreamSelectSubMenu(CMenu* pSub, UINT id, DWORD dwSelGroup)
    07925 {
    07926         UINT baseid = id;
    07927
    07928         CComQIPtr<IAMStreamSelect> pSS = FindFilter(CLSID_OggSplitter, pGB);
    07929         if(!pSS) pSS = FindFilter(L"{55DA30FC-F16B-49fc-BAA5-AE59FC65F82D}", pGB);
    07930         if(!pSS) return;
    07931
    07932         DWORD cStreams;
    07933         if(FAILED(pSS->Count(&cStreams)))
    07934                 return;
    07935
    07936         DWORD dwPrevGroup = -1;
    07937
    07938         for(int i = 0, j = cStreams; i < j; i++)
    07939         {
    07940                 DWORD dwFlags, dwGroup;
    07941                 LCID lcid;
    07942                 WCHAR* pszName = NULL;
    07943
    07944                 if(FAILED(pSS->Info(i, NULL, &dwFlags, &lcid, &dwGroup, &pszName, NULL, NULL))
    07945                 || !pszName)
    07946                         continue;
    07947
    07948                 CStringW name(pszName);
    07949                 name.MakeLower();
    07950
    07951                 if(pszName) CoTaskMemFree(pszName);
    07952
    07953                 if(dwGroup != dwSelGroup)
    07954                         continue;
    07955
    07956                 if(dwPrevGroup != -1 && dwPrevGroup != dwGroup)
    07957                         pSub->AppendMenu(MF_SEPARATOR);
    07958                 dwPrevGroup = dwGroup;
    07959
    07960                 CString str;
    07961
    07962                 if(name.Find(L" off") >= 0)
    07963                 {
    07964                         str = _T("Disabled");
    07965                 }
    07966                 else if(lcid == 0)
    07967                 {
    07968                         str.Format(_T("Unknown %d"), id - baseid);
    07969                 }
    07970                 else
    07971                 {
    07972                         int len = GetLocaleInfo(lcid, LOCALE_SENGLANGUAGE, str.GetBuffer(64), 64);
    07973                         str.ReleaseBufferSetLength(max(len-1, 0));
    07974                 }
    07975
    07976                 UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
    07977                 if(dwFlags) flags |= MF_CHECKED;
    07978
    07979                 str.Replace(_T("&"), _T("&&"));
    07980                 pSub->AppendMenu(flags, id++, str);
    07981         }
    07982 }
    07983
    07984 void CMainFrame::OnNavStreamSelectSubMenu(UINT id, DWORD dwSelGroup)
    07985 {
    07986         CComQIPtr<IAMStreamSelect> pSS = FindFilter(CLSID_OggSplitter, pGB);
    07987         if(!pSS) pSS = FindFilter(L"{55DA30FC-F16B-49fc-BAA5-AE59FC65F82D}", pGB);
    07988         if(!pSS) return;
    07989
    07990         DWORD cStreams;
    07991         if(FAILED(pSS->Count(&cStreams)))
    07992                 return;
    07993
    07994         for(int i = 0, j = cStreams; i < j; i++)
    07995         {
    07996                 DWORD dwFlags, dwGroup;
    07997                 LCID lcid;
    07998                 WCHAR* pszName = NULL;
    07999
    08000                 if(FAILED(pSS->Info(i, NULL, &dwFlags, &lcid, &dwGroup, &pszName, NULL, NULL))
    08001                 || !pszName)
    08002                         continue;
    08003
    08004                 if(pszName) CoTaskMemFree(pszName);
    08005
    08006                 if(dwGroup != dwSelGroup)
    08007                         continue;
    08008
    08009                 if(id == 0)
    08010                 {
    08011                         pSS->Enable(i, AMSTREAMSELECTENABLE_ENABLE);
    08012                         break;
    08013                 }
    08014
    08015                 id--;
    08016         }
    08017 }
    08018
    08019 void CMainFrame::SetupFavoritesSubMenu()
    08020 {
    08021         CMenu* pSub = &m_favorites;
    08022
    08023         if(!IsMenu(pSub->m_hMenu)) pSub->CreatePopupMenu();
    08024         else while(pSub->RemoveMenu(0, MF_BYPOSITION));
    08025
    08026         AppSettings& s = AfxGetAppSettings();
    08027
    08028         pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, ID_FAVORITES_ADD, _T("&Add to Favorites..."));
    08029         pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, ID_FAVORITES_ORGANIZE, _T("&Organize Favorites..."));
    08030
    08031         int nLastGroupStart = pSub->GetMenuItemCount();
    08032
    08033         UINT id = ID_FAVORITES_FILE_START;
    08034
    08035         CList<CString> sl;
    08036         AfxGetAppSettings().GetFav(FAV_FILE, sl);
    08037
    08038         POSITION pos = sl.GetHeadPosition();
    08039         while(pos)
    08040         {
    08041                 UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
    08042
    08043                 CString str = sl.GetNext(pos);
    08044                 str.Replace(_T("&"), _T("&&"));
    08045                 str.Replace(_T("\t"), _T(" "));
    08046
    08047                 CList<CString> sl;
    08048                 Explode(str, sl, ';', 2);
    08049
    08050                 str = sl.RemoveHead();
    08051
    08052                 if(!sl.IsEmpty())
    08053                 {
    08054                         REFERENCE_TIME rt = 0;
    08055                         if(1 == _stscanf(sl.GetHead(), _T("%I64d"), &rt) && rt > 0)
    08056                         {
    08057                                 DVD_HMSF_TIMECODE hmsf = RT2HMSF(rt, 0);
    08058                                 str.Format(_T("%s\t[%02d:%02d:%02d]"), CString(str), hmsf.bHours, hmsf.bMinutes, hmsf.bSeconds);
    08059                         }
    08060                 }
    08061
    08062                 if(!str.IsEmpty())
    08063                         pSub->AppendMenu(flags, id, str);
    08064
    08065                 id++;
    08066         }
    08067
    08068         if(id > ID_FAVORITES_FILE_START)
    08069                 pSub->InsertMenu(nLastGroupStart, MF_SEPARATOR|MF_ENABLED|MF_BYPOSITION);
    08070
    08071         nLastGroupStart = pSub->GetMenuItemCount();
    08072
    08073         id = ID_FAVORITES_DVD_START;
    08074
    08075         AfxGetAppSettings().GetFav(FAV_DVD, sl);
    08076
    08077         pos = sl.GetHeadPosition();
    08078         while(pos)
    08079         {
    08080                 UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
    08081
    08082                 CString str = sl.GetNext(pos);
    08083                 str.Replace(_T("&"), _T("&&"));
    08084
    08085                 CList<CString> sl;
    08086                 Explode(str, sl, ';', 2);
    08087
    08088                 str = sl.RemoveHead();
    08089
    08090                 if(!sl.IsEmpty())
    08091                 {
    08092                         // TODO
    08093                 }
    08094
    08095                 if(!str.IsEmpty())
    08096                         pSub->AppendMenu(flags, id, str);
    08097
    08098                 id++;
    08099         }
    08100
    08101         if(id > ID_FAVORITES_DVD_START)
    08102                 pSub->InsertMenu(nLastGroupStart, MF_SEPARATOR|MF_ENABLED|MF_BYPOSITION);
    08103
    08104         nLastGroupStart = pSub->GetMenuItemCount();
    08105
    08106         id = ID_FAVORITES_DEVICE_START;
    08107
    08108         AfxGetAppSettings().GetFav(FAV_DEVICE, sl);
    08109
    08110         pos = sl.GetHeadPosition();
    08111         while(pos)
    08112         {
    08113                 UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
    08114
    08115                 CString str = sl.GetNext(pos);
    08116                 str.Replace(_T("&"), _T("&&"));
    08117
    08118                 CList<CString> sl;
    08119                 Explode(str, sl, ';', 2);
    08120
    08121                 str = sl.RemoveHead();
    08122
    08123                 if(!str.IsEmpty())
    08124                         pSub->AppendMenu(flags, id, str);
    08125
    08126                 id++;
    08127         }
    08128 }
    08129
    08130 void CMainFrame::SetupShadersSubMenu()
    08131 {
    08132         CMenu* pSub = &m_shaders;
    08133
    08134         if(!IsMenu(pSub->m_hMenu)) pSub->CreatePopupMenu();
    08135         else while(pSub->RemoveMenu(0, MF_BYPOSITION));
    08136
    08137         CWinApp* pApp = AfxGetApp();
    08138
    08139         pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, ID_SHADERS_START, ResStr(IDS_SHADER_EDIT));
    08140
    08141         UINT id = ID_SHADERS_START+1;
    08142
    08143         for(int i = 0; ; i++)
    08144         {
    08145                 CString str;
    08146                 str.Format(_T("%d"), i);
    08147                 str = pApp->GetProfileString(_T("Shaders"), str);
    08148
    08149                 CList<CString> sl;
    08150                 CString label = Explode(str, sl, '|');
    08151                 if(label.IsEmpty()) break;
    08152
    08153                 UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
    08154
    08155                 if(i == 0)
    08156                 {
    08157                         pSub->AppendMenu(MF_SEPARATOR);
    08158                         pSub->AppendMenu(flags, id++, ResStr(IDS_SHADER_OFF));
    08159                 }
    08160
    08161                 label.Replace(_T("&"), _T("&&"));
    08162                 pSub->AppendMenu(flags, id++, label);
    08163         }
    08164 }
    08165
    08167
    08168 void CMainFrame::ShowControls(int nCS, bool fSave)
    08169 {
    08170         int nCSprev = AfxGetAppSettings().nCS;
    08171         int hbefore = 0, hafter = 0;
    08172
    08173         m_pLastBar = NULL;
    08174
    08175         POSITION pos = m_bars.GetHeadPosition();
    08176         for(int i = 1; pos; i <<= 1)
    08177         {
    08178                 CControlBar* pNext = m_bars.GetNext(pos);
    08179                 ShowControlBar(pNext, !!(nCS&i), TRUE);
    08180                 if(nCS&i) m_pLastBar = pNext;
    08181
    08182                 CSize s = pNext->CalcFixedLayout(FALSE, TRUE);
    08183                 if(nCSprev&i) hbefore += s.cy;
    08184                 if(nCS&i) hafter += s.cy;
    08185         }
    08186
    08187         WINDOWPLACEMENT wp;
    08188         wp.length = sizeof(wp);
    08189         GetWindowPlacement(&wp);
    08190
    08191         if(wp.showCmd != SW_SHOWMAXIMIZED && !m_fFullScreen)
    08192         {
    08193                 CRect r;
    08194                 GetWindowRect(r);
    08195                 MoveWindow(r.left, r.top, r.Width(), r.Height()+(hafter-hbefore));
    08196         }
    08197
    08198     if(fSave)
    08199                 AfxGetAppSettings().nCS = nCS;
    08200
    08201         RecalcLayout();
    08202 }
    08203
    08204 void CMainFrame::SetAlwaysOnTop(int i)
    08205 {
    08206         AfxGetAppSettings().iOnTop = i;
    08207
    08208         if(!m_fFullScreen)
    08209         {
    08210                 const CWnd* pInsertAfter = NULL;
    08211
    08212                 if(i == 0)
    08213                         pInsertAfter = &wndNoTopMost;
    08214                 else if(i == 1)
    08215                         pInsertAfter = &wndTopMost;
    08216                 else // if(i == 2)
    08217                         pInsertAfter = GetMediaState() == State_Running ? &wndTopMost : &wndNoTopMost;
    08218
    08219                 SetWindowPos(pInsertAfter, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
    08220         }
    08221         else if(!(GetWindowLong(m_hWnd, GWL_EXSTYLE)&WS_EX_TOPMOST))
    08222         {
    08223                 SetWindowPos(&wndTopMost, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
    08224         }
    08225 }
    08226
    08227 void CMainFrame::AddTextPassThruFilter()
    08228 {
    08229         BeginEnumFilters(pGB, pEF, pBF)
    08230         {
    08231                 if(!IsSplitter(pBF)) continue;
    08232
    08233                 BeginEnumPins(pBF, pEP, pPin)
    08234                 {
    08235                         CComPtr<IPin> pPinTo;
    08236                         AM_MEDIA_TYPE mt;
    08237                         if(FAILED(pPin->ConnectedTo(&pPinTo)) || !pPinTo
    08238                         || FAILED(pPin->ConnectionMediaType(&mt))
    08239                         || mt.majortype != MEDIATYPE_Text && mt.majortype != MEDIATYPE_Subtitle)
    08240                                 continue;
    08241
    08242                         CComQIPtr<IBaseFilter> pTPTF = new CTextPassThruFilter(this);
    08243                         CStringW name;
    08244                         name.Format(L"TextPassThru%08x", pTPTF);
    08245                         if(FAILED(pGB->AddFilter(pTPTF, name)))
    08246                                 continue;
    08247
    08248                         HRESULT hr;
    08249
    08250                         hr = pPinTo->Disconnect();
    08251                         hr = pPin->Disconnect();
    08252
    08253                         if(FAILED(hr = pGB->ConnectDirect(pPin, GetFirstPin(pTPTF, PINDIR_INPUT), NULL))
    08254                         || FAILED(hr = pGB->ConnectDirect(GetFirstPin(pTPTF, PINDIR_OUTPUT), pPinTo, NULL)))
    08255                                 hr = pGB->ConnectDirect(pPin, pPinTo, NULL);
    08256                         else
    08257                                 m_pSubStreams.AddTail(CComQIPtr<ISubStream>(pTPTF));
    08258                 }
    08259                 EndEnumPins
    08260         }
    08261         EndEnumFilters
    08262 }
    08263
    08264 bool CMainFrame::LoadSubtitle(CString fn)
    08265 {
    08266         CComPtr<ISubStream> pSubStream;
    08267
    08268         // TMP: maybe this will catch something for those who get a runtime error dialog when opening subtitles from cds
    08269         try
    08270         {
    08271                 if(!pSubStream)
    08272                 {
    08273                         CAutoPtr<CVobSubFile> pVSF(new CVobSubFile(&m_csSubLock));
    08274                         if(pVSF && pVSF->Open(fn) && pVSF->GetStreamCount() > 0)
    08275                                 pSubStream = pVSF.Detach();
    08276                 }
    08277
    08278                 if(!pSubStream)
    08279                 {
    08280                         CAutoPtr<CRenderedTextSubtitle> pRTS(new CRenderedTextSubtitle(&m_csSubLock));
    08281                         if(pRTS && pRTS->Open(fn, DEFAULT_CHARSET) && pRTS->GetStreamCount() > 0)
    08282                                 pSubStream = pRTS.Detach();
    08283                 }
    08284         }
    08285         catch(CException* e)
    08286         {
    08287                 e->Delete();
    08288         }
    08289
    08290         if(pSubStream)
    08291         {
    08292                 m_pSubStreams.AddTail(pSubStream);
    08293         }
    08294
    08295         return(!!pSubStream);
    08296 }
    08297
    08298 void CMainFrame::UpdateSubtitle(bool fApplyDefStyle)
    08299 {
    08300         if(!m_pCAP) return;
    08301
    08302         int i = m_iSubtitleSel;
    08303
    08304         POSITION pos = m_pSubStreams.GetHeadPosition();
    08305         while(pos && i >= 0)
    08306         {
    08307                 CComPtr<ISubStream> pSubStream = m_pSubStreams.GetNext(pos);
    08308
    08309                 if(i < pSubStream->GetStreamCount())
    08310                 {
    08311                         CAutoLock cAutoLock(&m_csSubLock);
    08312                         pSubStream->SetStream(i);
    08313                         SetSubtitle(pSubStream, fApplyDefStyle);
    08314                         return;
    08315                 }
    08316
    08317                 i -= pSubStream->GetStreamCount();
    08318         }
    08319
    08320         m_pCAP->SetSubPicProvider(NULL);
    08321 }
    08322
    08323 void CMainFrame::SetSubtitle(ISubStream* pSubStream, bool fApplyDefStyle)
    08324 {
    08325         AppSettings& s = AfxGetAppSettings();
    08326
    08327         if(pSubStream)
    08328         {
    08329                 CLSID clsid;
    08330                 pSubStream->GetClassID(&clsid);
    08331
    08332                 if(clsid == __uuidof(CVobSubFile))
    08333                 {
    08334                         CVobSubFile* pVSF = (CVobSubFile*)(ISubStream*)pSubStream;
    08335
    08336                         if(fApplyDefStyle)
    08337                         {
    08338                                 pVSF->SetAlignment(s.fOverridePlacement, s.nHorPos, s.nVerPos, 1, 1);
    08339                         }
    08340                 }
    08341                 if(clsid == __uuidof(CVobSubStream))
    08342                 {
    08343                         CVobSubStream* pVSS = (CVobSubStream*)(ISubStream*)pSubStream;
    08344
    08345                         if(fApplyDefStyle)
    08346                         {
    08347                                 pVSS->SetAlignment(s.fOverridePlacement, s.nHorPos, s.nVerPos, 1, 1);
    08348                         }
    08349                 }
    08350                 else if(clsid == __uuidof(CRenderedTextSubtitle))
    08351                 {
    08352                         CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)pSubStream;
    08353
    08354                         STSStyle style;
    08355
    08356                         if(fApplyDefStyle || pRTS->m_fUsingAutoGeneratedDefaultStyle)
    08357                         {
    08358                                 style = s.subdefstyle;
    08359
    08360                                 if(s.fOverridePlacement)
    08361                                 {
    08362                                         style.scrAlignment = 2;
    08363                                         int w = pRTS->m_dstScreenSize.cx;
    08364                                         int h = pRTS->m_dstScreenSize.cy;
    08365                                         int mw = w - style.marginRect.left - style.marginRect.right;
    08366                                         style.marginRect.bottom = h - MulDiv(h, s.nVerPos, 100);
    08367                                         style.marginRect.left = MulDiv(w, s.nHorPos, 100) - mw/2;
    08368                                         style.marginRect.right = w - (style.marginRect.left + mw);
    08369                                 }
    08370
    08371                                 pRTS->SetDefaultStyle(style);
    08372                         }
    08373
    08374                         if(pRTS->GetDefaultStyle(style) && style.relativeTo == 2)
    08375                         {
    08376                                 style.relativeTo = s.subdefstyle.relativeTo;
    08377                                 pRTS->SetDefaultStyle(style);
    08378                         }
    08379
    08380                         pRTS->Deinit();
    08381                 }
    08382         }
    08383
    08384         if(!fApplyDefStyle)
    08385         {
    08386                 m_iSubtitleSel = -1;
    08387
    08388                 if(pSubStream)
    08389                 {
    08390
    08391                 int i = 0;
    08392
    08393                 POSITION pos = m_pSubStreams.GetHeadPosition();
    08394                 while(pos)
    08395                 {
    08396                         CComPtr<ISubStream> pSubStream2 = m_pSubStreams.GetNext(pos);
    08397
    08398                         if(pSubStream == pSubStream2)
    08399                         {
    08400                                 m_iSubtitleSel = i + pSubStream2->GetStream();
    08401                                 break;
    08402                         }
    08403
    08404                         i += pSubStream2->GetStreamCount();
    08405                 }
    08406
    08407                 }
    08408         }
    08409
    08410         m_nSubtitleId = (DWORD_PTR)pSubStream;
    08411
    08412         if(m_pCAP)
    08413         {
    08414                 m_pCAP->SetSubPicProvider(CComQIPtr<ISubPicProvider>(pSubStream));
    08415                 m_wndSubresyncBar.SetSubtitle(pSubStream, m_pCAP->GetFPS());
    08416         }
    08417 }
    08418
    08419 void CMainFrame::ReplaceSubtitle(ISubStream* pSubStreamOld, ISubStream* pSubStreamNew)
    08420 {
    08421         POSITION pos = m_pSubStreams.GetHeadPosition();
    08422         while(pos)
    08423         {
    08424                 POSITION cur = pos;
    08425                 if(pSubStreamOld == m_pSubStreams.GetNext(pos))
    08426                 {
    08427                         m_pSubStreams.SetAt(cur, pSubStreamNew);
    08428                         UpdateSubtitle();
    08429                         break;
    08430                 }
    08431         }
    08432 }
    08433
    08434 void CMainFrame::InvalidateSubtitle(DWORD_PTR nSubtitleId, REFERENCE_TIME rtInvalidate)
    08435 {
    08436         if(m_pCAP)
    08437         {
    08438                 if(nSubtitleId == -1 || nSubtitleId == m_nSubtitleId)
    08439                         m_pCAP->Invalidate(rtInvalidate);
    08440         }
    08441 }
    08442
    08443 void CMainFrame::ReloadSubtitle()
    08444 {
    08445         POSITION pos = m_pSubStreams.GetHeadPosition();
    08446         while(pos) m_pSubStreams.GetNext(pos)->Reload();
    08447         UpdateSubtitle();
    08448 }
    08449
    08450 REFERENCE_TIME CMainFrame::GetPos()
    08451 {
    08452         return(m_iMediaLoadState == MLS_LOADED ? m_wndSeekBar.GetPos() : 0);
    08453 }
    08454
    08455 REFERENCE_TIME CMainFrame::GetDur()
    08456 {
    08457         __int64 start, stop;
    08458         m_wndSeekBar.GetRange(start, stop);
    08459         return(m_iMediaLoadState == MLS_LOADED ? stop : 0);
    08460 }
    08461
    08462 void CMainFrame::SeekTo(REFERENCE_TIME rtPos, bool fSeekToKeyFrame)
    08463 {
    08464         OAFilterState fs = GetMediaState();
    08465
    08466         if(rtPos < 0) rtPos = 0;
    08467
    08468         if(m_iPlaybackMode == PM_FILE)
    08469         {
    08470                 if(fs == State_Stopped)
    08471                         SendMessage(WM_COMMAND, ID_PLAY_PAUSE);
    08472
    08473                 HRESULT hr;
    08474
    08475                 if(fSeekToKeyFrame)
    08476                 {
    08477                         if(!m_kfs.IsEmpty())
    08478                         {
    08479                                 int i = rangebsearch(rtPos, m_kfs);
    08480                                 if(i >= 0 && i < m_kfs.GetCount())
    08481                                         rtPos = m_kfs[i];
    08482                         }
    08483                 }
    08484
    08485                 hr = pMS->SetPositions(&rtPos, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning);
    08486         }
    08487         else if(m_iPlaybackMode == PM_DVD && m_iDVDDomain == DVD_DOMAIN_Title)
    08488         {
    08489                 if(fs != State_Running)
    08490                         SendMessage(WM_COMMAND, ID_PLAY_PLAY);
    08491
    08492                 DVD_HMSF_TIMECODE tc = RT2HMSF(rtPos);
    08493                 pDVDC->PlayAtTime(&tc, DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
    08494
    08495 //              if(fs != State_Running)
    08496 //                      SendMessage(WM_COMMAND, ID_PLAY_PAUSE);
    08497         }
    08498         else if(m_iPlaybackMode == PM_CAPTURE)
    08499         {
    08500                 TRACE(_T("Warning (CMainFrame::SeekTo): Trying to seek in capture mode"));
    08501         }
    08502 }
    08503
    08504 void CMainFrame::CleanGraph()
    08505 {
    08506         if(!pGB) return;
    08507
    08508         BeginEnumFilters(pGB, pEF, pBF)
    08509         {
    08510                 CComQIPtr<IAMFilterMiscFlags> pAMMF(pBF);
    08511                 if(pAMMF && (pAMMF->GetMiscFlags()&AM_FILTER_MISC_FLAGS_IS_SOURCE))
    08512                         continue;
    08513
    08514                 // some capture filters forget to set AM_FILTER_MISC_FLAGS_IS_SOURCE
    08515                 // or to implement the IAMFilterMiscFlags interface
    08516                 if(pBF == pVidCap || pBF == pAudCap)
    08517                         continue;
    08518
    08519                 if(CComQIPtr<IFileSourceFilter>(pBF))
    08520                         continue;
    08521
    08522                 int nIn, nOut, nInC, nOutC;
    08523                 if(CountPins(pBF, nIn, nOut, nInC, nOutC) > 0 && (nInC+nOutC) == 0)
    08524                 {
    08525                         TRACE(CStringW(L"Removing: ") + GetFilterName(pBF) + '\n');
    08526
    08527                         pGB->RemoveFilter(pBF);
    08528                         pEF->Reset();
    08529                 }
    08530         }
    08531         EndEnumFilters
    08532 }
    08533
    08534 #define AUDIOBUFFERLEN 500
    08535
    08536 static void SetLatency(IBaseFilter* pBF, int cbBuffer)
    08537 {
    08538         BeginEnumPins(pBF, pEP, pPin)
    08539         {
    08540                 if(CComQIPtr<IAMBufferNegotiation> pAMBN = pPin)
    08541                 {
    08542                         ALLOCATOR_PROPERTIES ap;
    08543                         ap.cbAlign = -1;  // -1 means no preference.
    08544                         ap.cbBuffer = cbBuffer;
    08545                         ap.cbPrefix = -1;
    08546                         ap.cBuffers = -1;
    08547                         pAMBN->SuggestAllocatorProperties(&ap);
    08548                 }
    08549         }
    08550         EndEnumPins
    08551 }
    08552
    08553 HRESULT CMainFrame::BuildCapture(IPin* pPin, IBaseFilter* pBF[3], const GUID& majortype, AM_MEDIA_TYPE* pmt)
    08554 {
    08555         IBaseFilter* pBuff = pBF[0];
    08556         IBaseFilter* pEnc = pBF[1];
    08557         IBaseFilter* pMux = pBF[2];
    08558
    08559         if(!pPin || !pMux) return E_FAIL;
    08560
    08561         CString err;
    08562
    08563         HRESULT hr = S_OK;
    08564
    08565         AddFilterToGraph(pGB, pMux, L"Multiplexer");
    08566
    08567         IUnknown* pPrev = pPin;
    08568
    08569         CStringW prefix, prefixl;
    08570         if(majortype == MEDIATYPE_Video) prefix = L"Video ";
    08571         else if(majortype == MEDIATYPE_Audio) prefix = L"Audio ";
    08572         prefixl = prefix;
    08573         prefixl.MakeLower();
    08574
    08575         if(pBuff)
    08576         {
    08577                 hr = pGB->AddFilter(pBuff, prefix + L"Buffer");
    08578                 if(FAILED(hr))
    08579                 {
    08580                         err = _T("Can't add ") + CString(prefixl) + _T("buffer filter");
    08581                         AfxMessageBox(err);
    08582                         return hr;
    08583                 }
    08584
    08585                 hr = pCGB->RenderStream(NULL, &majortype, pPrev, NULL, pBuff);
    08586                 if(FAILED(hr))
    08587                 {
    08588                         err = _T("Error connecting the ") + CString(prefixl) + _T("buffer filter");
    08589                         AfxMessageBox(err);
    08590                         return(hr);
    08591                 }
    08592
    08593                 pPrev = pBuff;
    08594         }
    08595
    08596         if(pEnc)
    08597         {
    08598                 hr = pGB->AddFilter(pEnc, prefix + L"Encoder");
    08599                 if(FAILED(hr))
    08600                 {
    08601                         err = _T("Can't add ") + CString(prefixl) + _T("encoder filter");
    08602                         AfxMessageBox(err);
    08603                         return hr;
    08604                 }
    08605
    08606                 hr = pCGB->RenderStream(NULL, &majortype, pPrev, NULL, pEnc);
    08607                 if(FAILED(hr))
    08608                 {
    08609                         err = _T("Error connecting the ") + CString(prefixl) + _T("encoder filter");
    08610                         AfxMessageBox(err);
    08611                         return(hr);
    08612                 }
    08613
    08614                 pPrev = pEnc;
    08615
    08616                 if(CComQIPtr<IAMStreamConfig> pAMSC = GetFirstPin(pEnc, PINDIR_OUTPUT))
    08617                 {
    08618                         if(pmt->majortype == majortype)
    08619                         {
    08620                                 hr = pAMSC->SetFormat(pmt);
    08621                                 if(FAILED(hr))
    08622                                 {
    08623                                         err = _T("Can't set compression format on the ") + CString(prefixl) + _T("encoder filter");
    08624                                         AfxMessageBox(err);
    08625                                         return(hr);
    08626                                 }
    08627                         }
    08628                 }
    08629
    08630         }
    08631
    08632 //      if(pMux)
    08633         {
    08634                 hr = pCGB->RenderStream(NULL, &majortype, pPrev, NULL, pMux);
    08635                 if(FAILED(hr))
    08636                 {
    08637                         err = _T("Error connecting ") + CString(prefixl) + _T(" to the muliplexer filter");
    08638                         AfxMessageBox(err);
    08639                         return(hr);
    08640                 }
    08641         }
    08642
    08643         CleanGraph();
    08644
    08645         return S_OK;
    08646 }
    08647
    08648 bool CMainFrame::BuildToCapturePreviewPin(
    08649         IBaseFilter* pVidCap, IPin** ppVidCapPin, IPin** ppVidPrevPin,
    08650         IBaseFilter* pAudCap, IPin** ppAudCapPin, IPin** ppAudPrevPin)
    08651 {
    08652         HRESULT hr;
    08653
    08654         *ppVidCapPin = *ppVidPrevPin = NULL;
    08655         *ppAudCapPin = *ppAudPrevPin = NULL;
    08656
    08657         CComPtr<IPin> pDVAudPin;
    08658
    08659         if(pVidCap)
    08660         {
    08661                 CComPtr<IPin> pPin;
    08662                 if(!pAudCap // only look for interleaved stream when we don't use any other audio capture source
    08663                 && SUCCEEDED(pCGB->FindPin(pVidCap, PINDIR_OUTPUT, &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Interleaved, TRUE, 0, &pPin)))
    08664                 {
    08665                         CComPtr<IBaseFilter> pDVSplitter;
    08666                         hr = pDVSplitter.CoCreateInstance(CLSID_DVSplitter);
    08667                         hr = pGB->AddFilter(pDVSplitter, L"DV Splitter");
    08668
    08669                         hr = pCGB->RenderStream(NULL, &MEDIATYPE_Interleaved, pPin, NULL, pDVSplitter);
    08670
    08671                         pPin = NULL;
    08672                         hr = pCGB->FindPin(pDVSplitter, PINDIR_OUTPUT, NULL, &MEDIATYPE_Video, TRUE, 0, &pPin);
    08673                         hr = pCGB->FindPin(pDVSplitter, PINDIR_OUTPUT, NULL, &MEDIATYPE_Audio, TRUE, 0, &pDVAudPin);
    08674
    08675                         CComPtr<IBaseFilter> pDVDec;
    08676                         hr = pDVDec.CoCreateInstance(CLSID_DVVideoCodec);
    08677                         hr = pGB->AddFilter(pDVDec, L"DV Video Decoder");
    08678
    08679                         hr = pCGB->RenderStream(NULL, &MEDIATYPE_Video, pPin, NULL, pDVDec);
    08680
    08681                         pPin = NULL;
    08682                         hr = pCGB->FindPin(pDVDec, PINDIR_OUTPUT, NULL, &MEDIATYPE_Video, TRUE, 0, &pPin);
    08683                 }
    08684                 else if(SUCCEEDED(pCGB->FindPin(pVidCap, PINDIR_OUTPUT, &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, TRUE, 0, &pPin)))
    08685                 {
    08686                 }
    08687                 else
    08688                 {
    08689                         AfxMessageBox(_T("No video capture pin found"));
    08690                         return(false);
    08691                 }
    08692
    08693                 CComPtr<IBaseFilter> pSmartTee;
    08694                 hr = pSmartTee.CoCreateInstance(CLSID_SmartTee);
    08695                 hr = pGB->AddFilter(pSmartTee, L"Smart Tee (video)");
    08696
    08697                 hr = pCGB->RenderStream(NULL, &MEDIATYPE_Video, pPin, NULL, pSmartTee);
    08698
    08699                 hr = pSmartTee->FindPin(L"Preview", ppVidPrevPin);
    08700                 hr = pSmartTee->FindPin(L"Capture", ppVidCapPin);
    08701         }
    08702
    08703         if(pAudCap || pDVAudPin)
    08704         {
    08705                 CComPtr<IPin> pPin;
    08706                 if(pDVAudPin)
    08707                 {
    08708                         pPin = pDVAudPin;
    08709                 }
    08710                 else if(SUCCEEDED(pCGB->FindPin(pAudCap, PINDIR_OUTPUT, &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, TRUE, 0, &pPin)))
    08711                 {
    08712                 }
    08713                 else
    08714                 {
    08715                         AfxMessageBox(_T("No audio capture pin found"));
    08716                         return(false);
    08717                 }
    08718
    08719                 CComPtr<IBaseFilter> pSmartTee;
    08720                 hr = pSmartTee.CoCreateInstance(CLSID_SmartTee);
    08721                 hr = pGB->AddFilter(pSmartTee, L"Smart Tee (audio)");
    08722
    08723                 hr = pCGB->RenderStream(NULL, &MEDIATYPE_Audio, pPin, NULL, pSmartTee);
    08724
    08725                 hr = pSmartTee->FindPin(L"Preview", ppAudPrevPin);
    08726                 hr = pSmartTee->FindPin(L"Capture", ppAudCapPin);
    08727         }
    08728
    08729         return(true);
    08730 }
    08731
    08732 bool CMainFrame::BuildGraphVideoAudio(bool fVPreview, bool fVCapture, bool fAPreview, bool fACapture)
    08733 {
    08734         if(!pCGB) return(false);
    08735
    08736         SaveMediaState;
    08737
    08738         HRESULT hr;
    08739
    08740         NukeDownstream(pVidCap, pGB);
    08741         NukeDownstream(pAudCap, pGB);
    08742
    08743         CleanGraph();
    08744
    08745         if(pAMVSCCap) hr = pAMVSCCap->SetFormat(&m_wndCaptureBar.m_capdlg.m_mtv);
    08746         if(pAMVSCPrev) hr = pAMVSCPrev->SetFormat(&m_wndCaptureBar.m_capdlg.m_mtv);
    08747         if(pAMASC) hr = pAMASC->SetFormat(&m_wndCaptureBar.m_capdlg.m_mta);
    08748
    08749         CComPtr<IBaseFilter> pVidBuffer = m_wndCaptureBar.m_capdlg.m_pVidBuffer;
    08750         CComPtr<IBaseFilter> pAudBuffer = m_wndCaptureBar.m_capdlg.m_pAudBuffer;
    08751         CComPtr<IBaseFilter> pVidEnc = m_wndCaptureBar.m_capdlg.m_pVidEnc;
    08752         CComPtr<IBaseFilter> pAudEnc = m_wndCaptureBar.m_capdlg.m_pAudEnc;
    08753         CComPtr<IBaseFilter> pMux = m_wndCaptureBar.m_capdlg.m_pMux;
    08754         CComPtr<IBaseFilter> pDst = m_wndCaptureBar.m_capdlg.m_pDst;
    08755         CComPtr<IBaseFilter> pAudMux = m_wndCaptureBar.m_capdlg.m_pAudMux;
    08756         CComPtr<IBaseFilter> pAudDst = m_wndCaptureBar.m_capdlg.m_pAudDst;
    08757
    08758         bool fFileOutput = (pMux && pDst) || (pAudMux && pAudDst);
    08759         bool fCapture = (fVCapture || fACapture);
    08760
    08761         if(pAudCap)
    08762         {
    08763                 AM_MEDIA_TYPE* pmt = &m_wndCaptureBar.m_capdlg.m_mta;
    08764                 int ms = (fACapture && fFileOutput && m_wndCaptureBar.m_capdlg.m_fAudOutput) ? AUDIOBUFFERLEN : 60;
    08765                 if(pMux != pAudMux && fACapture) SetLatency(pAudCap, -1);
    08766                 else if(pmt->pbFormat) SetLatency(pAudCap, ((WAVEFORMATEX*)pmt->pbFormat)->nAvgBytesPerSec * ms / 1000);
    08767         }
    08768
    08769         CComPtr<IPin> pVidCapPin, pVidPrevPin, pAudCapPin, pAudPrevPin;
    08770         BuildToCapturePreviewPin(pVidCap, &pVidCapPin, &pVidPrevPin, pAudCap, &pAudCapPin, &pAudPrevPin);
    08771
    08772         CGraphBuilderCapture gb(pGB, m_wndView.m_hWnd);
    08773
    08774 //      if(pVidCap)
    08775         {
    08776                 bool fVidPrev = pVidPrevPin && fVPreview;
    08777                 bool fVidCap = pVidCapPin && fVCapture && fFileOutput && m_wndCaptureBar.m_capdlg.m_fVidOutput;
    08778
    08779                 if(fVidPrev && !fVidCap && pVidCapPin)
    08780                 {
    08781                         pVidPrevPin = pVidCapPin;
    08782                         pVidCapPin = NULL;
    08783                 }
    08784
    08785                 if(fVidPrev)
    08786                 {
    08787                         m_pCAP = NULL;
    08788                         gb.Render(pVidPrevPin);
    08789                         gb.FindInterface(__uuidof(ISubPicAllocatorPresenter), (void**)&m_pCAP);
    08790                 }
    08791
    08792                 if(fVidCap)
    08793                 {
    08794                         IBaseFilter* pBF[3] = {pVidBuffer, pVidEnc, pMux};
    08795                         HRESULT hr = BuildCapture(pVidCapPin, pBF, MEDIATYPE_Video, &m_wndCaptureBar.m_capdlg.m_mtcv);
    08796                 }
    08797
    08798                 pAMDF = NULL;
    08799                 pCGB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pVidCap, IID_IAMDroppedFrames, (void**)&pAMDF);
    08800         }
    08801
    08802 //      if(pAudCap)
    08803         {
    08804                 bool fAudPrev = pAudPrevPin && fAPreview;
    08805                 bool fAudCap = pAudCapPin && fACapture && fFileOutput && m_wndCaptureBar.m_capdlg.m_fAudOutput;
    08806
    08807                 if(fAudPrev)
    08808                 {
    08809                         gb.Render(fAudCap ? pAudPrevPin : pAudCapPin);
    08810                 }
    08811
    08812                 if(fAudCap)
    08813                 {
    08814                         IBaseFilter* pBF[3] = {pAudBuffer, pAudEnc, pAudMux ? pAudMux : pMux};
    08815                         HRESULT hr = BuildCapture(pAudCapPin, pBF, MEDIATYPE_Audio, &m_wndCaptureBar.m_capdlg.m_mtca);
    08816                 }
    08817         }
    08818
    08819         if((pVidCap || pAudCap) && fCapture && fFileOutput)
    08820         {
    08821                 if(pMux != pDst)
    08822                 {
    08823                         hr = pGB->AddFilter(pDst, L"File Writer V/A");
    08824                         hr = pCGB->RenderStream(NULL, NULL, pMux, NULL, pDst);
    08825                 }
    08826
    08827                 if(CComQIPtr<IConfigAviMux> pCAM = pMux)
    08828                 {
    08829                         int nIn, nOut, nInC, nOutC;
    08830                         CountPins(pMux, nIn, nOut, nInC, nOutC);
    08831                         pCAM->SetMasterStream(nInC-1);
    08832 //                      pCAM->SetMasterStream(-1);
    08833                         pCAM->SetOutputCompatibilityIndex(FALSE);
    08834                 }
    08835
    08836                 if(CComQIPtr<IConfigInterleaving> pCI = pMux)
    08837                 {
    08838 //                      if(FAILED(pCI->put_Mode(INTERLEAVE_CAPTURE)))
    08839                         if(FAILED(pCI->put_Mode(INTERLEAVE_NONE_BUFFERED)))
    08840                                 pCI->put_Mode(INTERLEAVE_NONE);
    08841
    08842                         REFERENCE_TIME rtInterleave = 10000i64*AUDIOBUFFERLEN, rtPreroll = 0;//10000i64*500
    08843                         pCI->put_Interleaving(&rtInterleave, &rtPreroll);
    08844                 }
    08845
    08846                 if(pMux != pAudMux && pAudMux != pAudDst)
    08847                 {
    08848                         hr = pGB->AddFilter(pAudDst, L"File Writer A");
    08849                         hr = pCGB->RenderStream(NULL, NULL, pAudMux, NULL, pAudDst);
    08850                 }
    08851         }
    08852
    08853         REFERENCE_TIME stop = MAX_TIME;
    08854         hr = pCGB->ControlStream(&PIN_CATEGORY_CAPTURE, NULL, NULL, NULL, &stop, 0, 0); // stop in the infinite
    08855
    08856         CleanGraph();
    08857
    08858         OpenSetupVideo();
    08859         OpenSetupStatsBar();
    08860         OpenSetupStatusBar();
    08861
    08862         RestoreMediaState;
    08863
    08864         return(true);
    08865 }
    08866
    08867 bool CMainFrame::StartCapture()
    08868 {
    08869         if(!pCGB || m_fCapturing) return(false);
    08870
    08871         if(!m_wndCaptureBar.m_capdlg.m_pMux && !m_wndCaptureBar.m_capdlg.m_pDst) return(false);
    08872
    08873         HRESULT hr;
    08874
    08875         ::SetPriorityClass(::GetCurrentProcess(), HIGH_PRIORITY_CLASS);
    08876
    08877         // rare to see two capture filters to support IAMPushSource at the same time...
    08878 //      hr = CComQIPtr<IAMGraphStreams>(pGB)->SyncUsingStreamOffset(TRUE); // TODO:
    08879
    08880         BuildGraphVideoAudio(
    08881                 !!m_wndCaptureBar.m_capdlg.m_fVidPreview, true,
    08882                 !!m_wndCaptureBar.m_capdlg.m_fAudPreview, true);
    08883
    08884         hr = pME->CancelDefaultHandling(EC_REPAINT);
    08885
    08886         SendMessage(WM_COMMAND, ID_PLAY_PLAY);
    08887
    08888         m_fCapturing = true;
    08889
    08890         return(true);
    08891 }
    08892
    08893 bool CMainFrame::StopCapture()
    08894 {
    08895         if(!pCGB || !m_fCapturing) return(false);
    08896
    08897         if(!m_wndCaptureBar.m_capdlg.m_pMux && !m_wndCaptureBar.m_capdlg.m_pDst) return(false);
    08898
    08899         HRESULT hr;
    08900
    08901         m_wndStatusBar.SetStatusMessage(_T("Completing..."));
    08902
    08903         m_fCapturing = false;
    08904
    08905         BuildGraphVideoAudio(
    08906                 !!m_wndCaptureBar.m_capdlg.m_fVidPreview, false,
    08907                 !!m_wndCaptureBar.m_capdlg.m_fAudPreview, false);
    08908
    08909         hr = pME->RestoreDefaultHandling(EC_REPAINT);
    08910
    08911         ::SetPriorityClass(::GetCurrentProcess(), AfxGetAppSettings().priority);
    08912
    08913         m_rtDurationOverride = -1;
    08914
    08915         return(true);
    08916 }
    08917
    08918 //
    08919
    08920 void CMainFrame::ShowOptions(int idPage)
    08921 {
    08922         AppSettings& s = AfxGetAppSettings();
    08923
    08924         CPPageSheet options(ResStr(IDS_OPTIONS_CAPTION), pGB, this, idPage);
    08925
    08926         if(options.DoModal() == IDOK)
    08927         {
    08928                 if(!m_fFullScreen)
    08929                         SetAlwaysOnTop(s.iOnTop);
    08930
    08931                 m_wndView.LoadLogo();
    08932
    08933                 s.UpdateData(true);
    08934         }
    08935 }
    08936
    08937 void CMainFrame::StartWebServer(int nPort)
    08938 {
    08939         if(!m_pWebServer)
    08940                 m_pWebServer.Attach(new CWebServer(this, nPort));
    08941 }
    08942
    08943 void CMainFrame::StopWebServer()
    08944 {
    08945         if(m_pWebServer)
    08946                 m_pWebServer.Free();
    08947 }
    08948
    08949 CString CMainFrame::GetStatusMessage()
    08950 {
    08951         CString str;
    08952         m_wndStatusBar.m_status.GetWindowText(str);
    08953         return str;
    08954 }
    08955
    08956 void CMainFrame::SendStatusMessage(CString msg, int nTimeOut)
    08957 {
    08958         KillTimer(TIMER_STATUSERASER);
    08959
    08960         m_playingmsg.Empty();
    08961         if(nTimeOut <= 0) return;
    08962
    08963         m_playingmsg = msg;
    08964         SetTimer(TIMER_STATUSERASER, nTimeOut, NULL);
    08965 }
    08966
    08967 void CMainFrame::OpenCurPlaylistItem(REFERENCE_TIME rtStart)
    08968 {
    08969         if(m_wndPlaylistBar.GetCount() == 0)
    08970                 return;
    08971
    08972         CPlaylistItem pli;
    08973         if(!m_wndPlaylistBar.GetCur(pli)) m_wndPlaylistBar.SetFirst();
    08974         if(!m_wndPlaylistBar.GetCur(pli)) return;
    08975
    08976         CAutoPtr<OpenMediaData> p(m_wndPlaylistBar.GetCurOMD(rtStart));
    08977         if(p) OpenMedia(p);
    08978 }
    08979
    08980 void CMainFrame::AddCurDevToPlaylist()
    08981 {
    08982         if(m_iPlaybackMode == PM_CAPTURE)
    08983         {
    08984                 m_wndPlaylistBar.Append(
    08985                         m_VidDispName,
    08986                         m_AudDispName,
    08987                         m_wndCaptureBar.m_capdlg.GetVideoInput(),
    08988                         m_wndCaptureBar.m_capdlg.GetVideoChannel(),
    08989                         m_wndCaptureBar.m_capdlg.GetAudioInput()
    08990                         );
    08991         }
    08992 }
    08993
    08994 static int s_fOpenedThruThread = false;
    08995
    08996 void CMainFrame::OpenMedia(CAutoPtr<OpenMediaData> pOMD)
    08997 {
    08998         // shortcut
    08999         if(OpenDeviceData* p = dynamic_cast<OpenDeviceData*>(pOMD.m_p))
    09000         {
    09001                 if(m_iMediaLoadState == MLS_LOADED && pAMTuner
    09002                 && m_VidDispName == p->DisplayName[0] && m_AudDispName == p->DisplayName[1])
    09003                 {
    09004                         m_wndCaptureBar.m_capdlg.SetVideoInput(p->vinput);
    09005                         m_wndCaptureBar.m_capdlg.SetVideoChannel(p->vchannel);
    09006                         m_wndCaptureBar.m_capdlg.SetAudioInput(p->ainput);
    09007                         SendNowPlayingToMSN();
    09008                         return;
    09009                 }
    09010         }
    09011
    09012         if(m_iMediaLoadState != MLS_CLOSED)
    09013                 CloseMedia();
    09014
    09015         AppSettings& s = AfxGetAppSettings();
    09016
    09017         bool fUseThread = true;
    09018
    09019         if(OpenFileData* p = dynamic_cast<OpenFileData*>(pOMD.m_p))
    09020         {
    09021                 if(p->fns.GetCount() > 0)
    09022                 {
    09023                         engine_t e = s.Formats.GetEngine(p->fns.GetHead());
    09024                         fUseThread = e == DirectShow /*|| e == RealMedia || e == QuickTime*/;
    09025                 }
    09026         }
    09027         else if(OpenDeviceData* p = dynamic_cast<OpenDeviceData*>(pOMD.m_p))
    09028         {
    09029                 fUseThread = false;
    09030         }
    09031
    09032         if(m_pGraphThread && fUseThread
    09033         && AfxGetAppSettings().fEnableWorkerThreadForOpening)
    09034         {
    09035                 m_pGraphThread->PostThreadMessage(CGraphThread::TM_OPEN, 0, (LPARAM)pOMD.Detach());
    09036                 s_fOpenedThruThread = true;
    09037         }
    09038         else
    09039         {
    09040                 OpenMediaPrivate(pOMD);
    09041                 s_fOpenedThruThread = false;
    09042         }
    09043 }
    09044
    09045 void CMainFrame::CloseMedia()
    09046 {
    09047         if(m_iMediaLoadState == MLS_CLOSING)
    09048         {
    09049                 TRACE(_T("WARNING: CMainFrame::CloseMedia() called twice or more\n"));
    09050                 return;
    09051         }
    09052
    09053         int nTimeWaited = 0;
    09054
    09055         while(m_iMediaLoadState == MLS_LOADING)
    09056         {
    09057                 m_fOpeningAborted = true;
    09058
    09059                 if(pGB) pGB->Abort(); // TODO: lock on graph objects somehow, this is not thread safe
    09060
    09061                 if(nTimeWaited > 5*1000 && m_pGraphThread)
    09062                 {
    09063                         MessageBeep(MB_ICONEXCLAMATION);
    09064                         TRACE(_T("CRITICAL ERROR: !!! Must kill opener thread !!!"));
    09065                         TerminateThread(m_pGraphThread->m_hThread, -1);
    09066                         m_pGraphThread = (CGraphThread*)AfxBeginThread(RUNTIME_CLASS(CGraphThread));
    09067                         s_fOpenedThruThread = false;
    09068                         break;
    09069                 }
    09070
    09071                 Sleep(50);
    09072
    09073                 nTimeWaited += 50;
    09074         }
    09075
    09076         m_fOpeningAborted = false;
    09077
    09078         m_closingmsg.Empty();
    09079
    09080         m_iMediaLoadState = MLS_CLOSING;
    09081
    09082         OnFilePostClosemedia();
    09083
    09084         if(m_pGraphThread && s_fOpenedThruThread)
    09085         {
    09086                 CAMEvent e;
    09087                 m_pGraphThread->PostThreadMessage(CGraphThread::TM_CLOSE, 0, (LPARAM)&e);
    09088                 e.Wait(); // either opening or closing has to be blocked to prevent reentering them, closing is the better choice
    09089         }
    09090         else
    09091         {
    09092                 CloseMediaPrivate();
    09093         }
    09094
    09095         UnloadExternalObjects();
    09096 }
    09097
    09098 //
    09099 // CGraphThread
    09100 //
    09101
    09102 IMPLEMENT_DYNCREATE(CGraphThread, CWinThread)
    09103
    09104 BOOL CGraphThread::InitInstance()
    09105 {
    09106         AfxSocketInit();
    09107         return SUCCEEDED(CoInitialize(0)) ? TRUE : FALSE;
    09108 }
    09109
    09110 int CGraphThread::ExitInstance()
    09111 {
    09112         CoUninitialize();
    09113         return __super::ExitInstance();
    09114 }
    09115
    09116 BEGIN_MESSAGE_MAP(CGraphThread, CWinThread)
    09117         ON_THREAD_MESSAGE(TM_EXIT, OnExit)
    09118         ON_THREAD_MESSAGE(TM_OPEN, OnOpen)
    09119         ON_THREAD_MESSAGE(TM_CLOSE, OnClose)
    09120 END_MESSAGE_MAP()
    09121
    09122 void CGraphThread::OnExit(WPARAM wParam, LPARAM lParam)
    09123 {
    09124         PostQuitMessage(0);
    09125         if(CAMEvent* e = (CAMEvent*)lParam) e->Set();
    09126 }
    09127
    09128 void CGraphThread::OnOpen(WPARAM wParam, LPARAM lParam)
    09129 {
    09130         if(m_pMainFrame)
    09131         {
    09132                 CAutoPtr<OpenMediaData> pOMD((OpenMediaData*)lParam);
    09133                 m_pMainFrame->OpenMediaPrivate(pOMD);
    09134         }
    09135 }
    09136
    09137 void CGraphThread::OnClose(WPARAM wParam, LPARAM lParam)
    09138 {
    09139         if(m_pMainFrame) m_pMainFrame->CloseMediaPrivate();
    09140         if(CAMEvent* e = (CAMEvent*)lParam) e->Set();
    09141 }
    09142
    09143