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 

Generated on Tue Dec 13 14:46:55 2005 for guliverkli by  doxygen 1.4.5