Support unrar64.dll
[xy_vsfilter.git] / src / apps / mplayerc / MainFrm.cpp
blobf8a1d0d2729071d1839502cf14a09af7831b91f5
1 /*
2 * Copyright (C) 2003-2006 Gabest
3 * http://www.gabest.org
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GNU Make; see the file COPYING. If not, write to
17 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18 * http://www.gnu.org/copyleft/gpl.html
22 // MainFrm.cpp : implementation of the CMainFrame class
25 #include "stdafx.h"
26 #include "mplayerc.h"
28 #include "MainFrm.h"
30 #include <math.h>
32 #include <afxpriv.h>
34 #include <atlconv.h>
35 #include <atlrx.h>
36 #include <atlsync.h>
38 #include "OpenFileDlg.h"
39 #include "OpenDlg.h"
40 #include "SaveDlg.h"
41 #include "GoToDlg.h"
42 #include "PnSPresetsDlg.h"
43 #include "MediaTypesDlg.h"
44 #include "SaveTextFileDialog.h"
45 #include "SaveThumbnailsDialog.h"
46 #include "FavoriteAddDlg.h"
47 #include "FavoriteOrganizeDlg.h"
48 #include "ConvertDlg.h"
49 #include "ShaderCombineDlg.h"
51 #include <mtype.h>
52 #include <Mpconfig.h>
53 #include <ks.h>
54 #include <ksmedia.h>
55 #include <dvdevcod.h>
56 #include <dsound.h>
58 #include <initguid.h>
59 #include <uuids.h>
60 #include "..\..\..\include\moreuuids.h"
61 #include <Qnetwork.h>
62 //#include <qedit.h>
64 #include "..\..\DSUtil\DSUtil.h"
65 #include "FGManager.h"
67 #include "textpassthrufilter.h"
68 #include "..\..\filters\filters.h"
69 #include "..\..\filters\PinInfoWnd.h"
71 #include "DX7AllocatorPresenter.h"
72 #include "DX9AllocatorPresenter.h"
74 #include "..\..\subtitles\SSF.h"
76 #define DEFCLIENTW 292
77 #define DEFCLIENTH 200
79 static UINT s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
80 static UINT WM_NOTIFYICON = RegisterWindowMessage(TEXT("MYWM_NOTIFYICON"));
82 #include "..\..\filters\transform\vsfilter\IDirectVobSub.h"
84 class CSubClock : public CUnknown, public ISubClock
86 STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv)
88 return
89 QI(ISubClock)
90 CUnknown::NonDelegatingQueryInterface(riid, ppv);
93 REFERENCE_TIME m_rt;
95 public:
96 CSubClock() : CUnknown(NAME("CSubClock"), NULL) {m_rt = 0;}
98 DECLARE_IUNKNOWN;
100 // ISubClock
101 STDMETHODIMP SetTime(REFERENCE_TIME rt) {m_rt = rt; return S_OK;}
102 STDMETHODIMP_(REFERENCE_TIME) GetTime() {return(m_rt);}
107 #define SaveMediaState \
108 OAFilterState __fs = GetMediaState(); \
110 REFERENCE_TIME __rt = 0; \
111 if(m_iMediaLoadState == MLS_LOADED) __rt = GetPos(); \
113 if(__fs != State_Stopped) \
114 SendMessage(WM_COMMAND, ID_PLAY_STOP); \
117 #define RestoreMediaState \
118 if(m_iMediaLoadState == MLS_LOADED) \
120 SeekTo(__rt); \
122 if(__fs == State_Stopped) \
123 SendMessage(WM_COMMAND, ID_PLAY_STOP); \
124 else if(__fs == State_Paused) \
125 SendMessage(WM_COMMAND, ID_PLAY_PAUSE); \
126 else if(__fs == State_Running) \
127 SendMessage(WM_COMMAND, ID_PLAY_PLAY); \
131 #ifdef _DEBUG
132 #define new DEBUG_NEW
133 #undef THIS_FILE
134 static char THIS_FILE[] = __FILE__;
135 #endif
137 /////////////////////////////////////////////////////////////////////////////
138 // CMainFrame
140 IMPLEMENT_DYNAMIC(CMainFrame, CFrameWnd)
142 BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
143 ON_WM_CREATE()
144 ON_WM_DESTROY()
145 ON_WM_CLOSE()
147 ON_REGISTERED_MESSAGE(s_uTaskbarRestart, OnTaskBarRestart)
148 ON_REGISTERED_MESSAGE(WM_NOTIFYICON, OnNotifyIcon)
150 ON_WM_SETFOCUS()
151 ON_WM_GETMINMAXINFO()
152 ON_WM_MOVE()
153 ON_WM_MOVING()
154 ON_WM_SIZE()
155 ON_WM_SIZING()
156 ON_MESSAGE_VOID(WM_DISPLAYCHANGE, OnDisplayChange)
158 ON_WM_SYSCOMMAND()
159 ON_WM_ACTIVATEAPP()
160 ON_MESSAGE(WM_APPCOMMAND, OnAppCommand)
162 ON_WM_TIMER()
164 ON_MESSAGE(WM_GRAPHNOTIFY, OnGraphNotify)
165 ON_MESSAGE(WM_REARRANGERENDERLESS, OnRepaintRenderLess)
166 ON_MESSAGE(WM_RESUMEFROMSTATE, OnResumeFromState)
168 ON_WM_LBUTTONDOWN()
169 ON_WM_LBUTTONUP()
170 ON_WM_LBUTTONDBLCLK()
171 ON_WM_MBUTTONDOWN()
172 ON_WM_MBUTTONUP()
173 ON_WM_MBUTTONDBLCLK()
174 ON_WM_RBUTTONDOWN()
175 ON_WM_RBUTTONUP()
176 ON_WM_RBUTTONDBLCLK()
177 ON_MESSAGE(WM_XBUTTONDOWN, OnXButtonDown)
178 ON_MESSAGE(WM_XBUTTONUP, OnXButtonUp)
179 ON_MESSAGE(WM_XBUTTONDBLCLK, OnXButtonDblClk)
180 ON_WM_MOUSEWHEEL()
181 ON_WM_MOUSEMOVE()
183 ON_WM_NCHITTEST()
185 ON_WM_HSCROLL()
187 ON_WM_INITMENU()
188 ON_WM_INITMENUPOPUP()
190 ON_COMMAND(ID_MENU_PLAYER_SHORT, OnMenuPlayerShort)
191 ON_COMMAND(ID_MENU_PLAYER_LONG, OnMenuPlayerLong)
192 ON_COMMAND(ID_MENU_FILTERS, OnMenuFilters)
194 ON_UPDATE_COMMAND_UI(IDC_PLAYERSTATUS, OnUpdatePlayerStatus)
196 ON_COMMAND(ID_FILE_POST_OPENMEDIA, OnFilePostOpenmedia)
197 ON_UPDATE_COMMAND_UI(ID_FILE_POST_OPENMEDIA, OnUpdateFilePostOpenmedia)
198 ON_COMMAND(ID_FILE_POST_CLOSEMEDIA, OnFilePostClosemedia)
199 ON_UPDATE_COMMAND_UI(ID_FILE_POST_CLOSEMEDIA, OnUpdateFilePostClosemedia)
201 ON_COMMAND(ID_BOSS, OnBossKey)
203 ON_COMMAND_RANGE(ID_STREAM_AUDIO_NEXT, ID_STREAM_AUDIO_PREV, OnStreamAudio)
204 ON_COMMAND_RANGE(ID_STREAM_SUB_NEXT, ID_STREAM_SUB_PREV, OnStreamSub)
205 ON_COMMAND(ID_STREAM_SUB_ONOFF, OnStreamSubOnOff)
206 ON_COMMAND_RANGE(ID_OGM_AUDIO_NEXT, ID_OGM_AUDIO_PREV, OnOgmAudio)
207 ON_COMMAND_RANGE(ID_OGM_SUB_NEXT, ID_OGM_SUB_PREV, OnOgmSub)
208 ON_COMMAND_RANGE(ID_DVD_ANGLE_NEXT, ID_DVD_ANGLE_PREV, OnDvdAngle)
209 ON_COMMAND_RANGE(ID_DVD_AUDIO_NEXT, ID_DVD_AUDIO_PREV, OnDvdAudio)
210 ON_COMMAND_RANGE(ID_DVD_SUB_NEXT, ID_DVD_SUB_PREV, OnDvdSub)
211 ON_COMMAND(ID_DVD_SUB_ONOFF, OnDvdSubOnOff)
214 ON_COMMAND(ID_FILE_OPENQUICK, OnFileOpenQuick)
215 ON_UPDATE_COMMAND_UI(ID_FILE_OPENMEDIA, OnUpdateFileOpen)
216 ON_COMMAND(ID_FILE_OPENMEDIA, OnFileOpenmedia)
217 ON_UPDATE_COMMAND_UI(ID_FILE_OPENMEDIA, OnUpdateFileOpen)
218 ON_WM_COPYDATA()
219 ON_COMMAND(ID_FILE_OPENDVD, OnFileOpendvd)
220 ON_UPDATE_COMMAND_UI(ID_FILE_OPENDVD, OnUpdateFileOpen)
221 ON_COMMAND(ID_FILE_OPENDEVICE, OnFileOpendevice)
222 ON_UPDATE_COMMAND_UI(ID_FILE_OPENDEVICE, OnUpdateFileOpen)
223 ON_COMMAND_RANGE(ID_FILE_OPEN_CD_START, ID_FILE_OPEN_CD_END, OnFileOpenCD)
224 ON_UPDATE_COMMAND_UI_RANGE(ID_FILE_OPEN_CD_START, ID_FILE_OPEN_CD_END, OnUpdateFileOpen)
225 ON_WM_DROPFILES()
226 ON_COMMAND(ID_FILE_SAVE_COPY, OnFileSaveAs)
227 ON_UPDATE_COMMAND_UI(ID_FILE_SAVE_COPY, OnUpdateFileSaveAs)
228 ON_COMMAND(ID_FILE_SAVE_IMAGE, OnFileSaveImage)
229 ON_UPDATE_COMMAND_UI(ID_FILE_SAVE_IMAGE, OnUpdateFileSaveImage)
230 ON_COMMAND(ID_FILE_SAVE_IMAGE_AUTO, OnFileSaveImageAuto)
231 ON_UPDATE_COMMAND_UI(ID_FILE_SAVE_IMAGE_AUTO, OnUpdateFileSaveImage)
232 ON_COMMAND(ID_FILE_SAVE_THUMBNAILS, OnFileSaveThumbnails)
233 ON_UPDATE_COMMAND_UI(ID_FILE_SAVE_THUMBNAILS, OnUpdateFileSaveThumbnails)
234 ON_COMMAND(ID_FILE_CONVERT, OnFileConvert)
235 ON_UPDATE_COMMAND_UI(ID_FILE_CONVERT, OnUpdateFileConvert)
236 ON_COMMAND(ID_FILE_LOAD_SUBTITLE, OnFileLoadsubtitle)
237 ON_UPDATE_COMMAND_UI(ID_FILE_LOAD_SUBTITLE, OnUpdateFileLoadsubtitle)
238 ON_COMMAND(ID_FILE_SAVE_SUBTITLE, OnFileSavesubtitle)
239 ON_UPDATE_COMMAND_UI(ID_FILE_SAVE_SUBTITLE, OnUpdateFileSavesubtitle)
240 ON_COMMAND(ID_FILE_ISDB_SEARCH, OnFileISDBSearch)
241 ON_UPDATE_COMMAND_UI(ID_FILE_ISDB_SEARCH, OnUpdateFileISDBSearch)
242 ON_COMMAND(ID_FILE_ISDB_UPLOAD, OnFileISDBUpload)
243 ON_UPDATE_COMMAND_UI(ID_FILE_ISDB_UPLOAD, OnUpdateFileISDBUpload)
244 ON_COMMAND(ID_FILE_ISDB_DOWNLOAD, OnFileISDBDownload)
245 ON_UPDATE_COMMAND_UI(ID_FILE_ISDB_DOWNLOAD, OnUpdateFileISDBDownload)
246 ON_COMMAND(ID_FILE_PROPERTIES, OnFileProperties)
247 ON_UPDATE_COMMAND_UI(ID_FILE_PROPERTIES, OnUpdateFileProperties)
248 ON_COMMAND(ID_FILE_CLOSEPLAYLIST, OnFileClosePlaylist)
249 ON_COMMAND(ID_FILE_CLOSEMEDIA, OnFileCloseMedia)
250 ON_UPDATE_COMMAND_UI(ID_FILE_CLOSEMEDIA, OnUpdateFileClose)
252 ON_COMMAND(ID_VIEW_CAPTIONMENU, OnViewCaptionmenu)
253 ON_UPDATE_COMMAND_UI(ID_VIEW_CAPTIONMENU, OnUpdateViewCaptionmenu)
254 ON_COMMAND_RANGE(ID_VIEW_SEEKER, ID_VIEW_STATUS, OnViewControlBar)
255 ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_SEEKER, ID_VIEW_STATUS, OnUpdateViewControlBar)
256 ON_COMMAND(ID_VIEW_SUBRESYNC, OnViewSubresync)
257 ON_UPDATE_COMMAND_UI(ID_VIEW_SUBRESYNC, OnUpdateViewSubresync)
258 ON_COMMAND(ID_VIEW_PLAYLIST, OnViewPlaylist)
259 ON_UPDATE_COMMAND_UI(ID_VIEW_PLAYLIST, OnUpdateViewPlaylist)
260 ON_COMMAND(ID_VIEW_CAPTURE, OnViewCapture)
261 ON_UPDATE_COMMAND_UI(ID_VIEW_CAPTURE, OnUpdateViewCapture)
262 ON_COMMAND(ID_VIEW_SHADEREDITOR, OnViewShaderEditor)
263 ON_UPDATE_COMMAND_UI(ID_VIEW_SHADEREDITOR, OnUpdateViewShaderEditor)
264 ON_COMMAND(ID_VIEW_PRESETS_MINIMAL, OnViewMinimal)
265 ON_UPDATE_COMMAND_UI(ID_VIEW_PRESETS_MINIMAL, OnUpdateViewMinimal)
266 ON_COMMAND(ID_VIEW_PRESETS_COMPACT, OnViewCompact)
267 ON_UPDATE_COMMAND_UI(ID_VIEW_PRESETS_COMPACT, OnUpdateViewCompact)
268 ON_COMMAND(ID_VIEW_PRESETS_NORMAL, OnViewNormal)
269 ON_UPDATE_COMMAND_UI(ID_VIEW_PRESETS_NORMAL, OnUpdateViewNormal)
270 ON_COMMAND(ID_VIEW_FULLSCREEN, OnViewFullscreen)
271 ON_COMMAND(ID_VIEW_FULLSCREEN_SECONDARY, OnViewFullscreenSecondary)
272 ON_UPDATE_COMMAND_UI(ID_VIEW_FULLSCREEN, OnUpdateViewFullscreen)
273 ON_COMMAND_RANGE(ID_VIEW_ZOOM_50, ID_VIEW_ZOOM_200, OnViewZoom)
274 ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_ZOOM_50, ID_VIEW_ZOOM_200, OnUpdateViewZoom)
275 ON_COMMAND(ID_VIEW_ZOOM_AUTOFIT, OnViewZoomAutoFit)
276 ON_UPDATE_COMMAND_UI(ID_VIEW_ZOOM_AUTOFIT, OnUpdateViewZoom)
277 ON_COMMAND_RANGE(ID_VIEW_VF_HALF, ID_VIEW_VF_FROMOUTSIDE, OnViewDefaultVideoFrame)
278 ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_VF_HALF, ID_VIEW_VF_FROMOUTSIDE, OnUpdateViewDefaultVideoFrame)
279 ON_COMMAND(ID_VIEW_VF_KEEPASPECTRATIO, OnViewKeepaspectratio)
280 ON_UPDATE_COMMAND_UI(ID_VIEW_VF_KEEPASPECTRATIO, OnUpdateViewKeepaspectratio)
281 ON_COMMAND(ID_VIEW_VF_COMPMONDESKARDIFF, OnViewCompMonDeskARDiff)
282 ON_UPDATE_COMMAND_UI(ID_VIEW_VF_COMPMONDESKARDIFF, OnUpdateViewCompMonDeskARDiff)
283 ON_COMMAND_RANGE(ID_VIEW_RESET, ID_PANSCAN_CENTER, OnViewPanNScan)
284 ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_RESET, ID_PANSCAN_CENTER, OnUpdateViewPanNScan)
285 ON_COMMAND_RANGE(ID_PANNSCAN_PRESETS_START, ID_PANNSCAN_PRESETS_END, OnViewPanNScanPresets)
286 ON_UPDATE_COMMAND_UI_RANGE(ID_PANNSCAN_PRESETS_START, ID_PANNSCAN_PRESETS_END, OnUpdateViewPanNScanPresets)
287 ON_COMMAND_RANGE(ID_PANSCAN_ROTATEXP, ID_PANSCAN_ROTATEZM, OnViewRotate)
288 ON_UPDATE_COMMAND_UI_RANGE(ID_PANSCAN_ROTATEXP, ID_PANSCAN_ROTATEZM, OnUpdateViewRotate)
289 ON_COMMAND_RANGE(ID_ASPECTRATIO_START, ID_ASPECTRATIO_END, OnViewAspectRatio)
290 ON_UPDATE_COMMAND_UI_RANGE(ID_ASPECTRATIO_START, ID_ASPECTRATIO_END, OnUpdateViewAspectRatio)
291 ON_COMMAND(ID_ASPECTRATIO_NEXT, OnViewAspectRatioNext)
292 ON_COMMAND_RANGE(ID_ONTOP_NEVER, ID_ONTOP_WHILEPLAYING, OnViewOntop)
293 ON_UPDATE_COMMAND_UI_RANGE(ID_ONTOP_NEVER, ID_ONTOP_WHILEPLAYING, OnUpdateViewOntop)
294 ON_COMMAND(ID_VIEW_OPTIONS, OnViewOptions)
296 ON_COMMAND_RANGE(ID_SUB_DELAY_DOWN, ID_SUB_DELAY_UP, OnSubtitleDelay)
298 ON_COMMAND(ID_PLAY_PLAY, OnPlayPlay)
299 ON_COMMAND(ID_PLAY_PAUSE, OnPlayPause)
300 ON_COMMAND(ID_PLAY_PLAYPAUSE, OnPlayPlaypause)
301 ON_COMMAND(ID_PLAY_STOP, OnPlayStop)
302 ON_UPDATE_COMMAND_UI(ID_PLAY_PLAY, OnUpdatePlayPauseStop)
303 ON_UPDATE_COMMAND_UI(ID_PLAY_PAUSE, OnUpdatePlayPauseStop)
304 ON_UPDATE_COMMAND_UI(ID_PLAY_PLAYPAUSE, OnUpdatePlayPauseStop)
305 ON_UPDATE_COMMAND_UI(ID_PLAY_STOP, OnUpdatePlayPauseStop)
306 ON_COMMAND_RANGE(ID_PLAY_FRAMESTEP, ID_PLAY_FRAMESTEPCANCEL, OnPlayFramestep)
307 ON_UPDATE_COMMAND_UI_RANGE(ID_PLAY_FRAMESTEP, ID_PLAY_FRAMESTEPCANCEL, OnUpdatePlayFramestep)
308 ON_COMMAND_RANGE(ID_PLAY_SEEKBACKWARDSMALL, ID_PLAY_SEEKFORWARDLARGE, OnPlaySeek)
309 ON_COMMAND_RANGE(ID_PLAY_SEEKKEYBACKWARD, ID_PLAY_SEEKKEYFORWARD, OnPlaySeekKey)
310 ON_UPDATE_COMMAND_UI_RANGE(ID_PLAY_SEEKBACKWARDSMALL, ID_PLAY_SEEKFORWARDLARGE, OnUpdatePlaySeek)
311 ON_UPDATE_COMMAND_UI_RANGE(ID_PLAY_SEEKKEYBACKWARD, ID_PLAY_SEEKKEYFORWARD, OnUpdatePlaySeek)
312 ON_COMMAND(ID_PLAY_GOTO, OnPlayGoto)
313 ON_UPDATE_COMMAND_UI(ID_PLAY_GOTO, OnUpdateGoto)
314 ON_COMMAND_RANGE(ID_PLAY_DECRATE, ID_PLAY_INCRATE, OnPlayChangeRate)
315 ON_UPDATE_COMMAND_UI_RANGE(ID_PLAY_DECRATE, ID_PLAY_INCRATE, OnUpdatePlayChangeRate)
316 ON_COMMAND(ID_PLAY_RESETRATE, OnPlayResetRate)
317 ON_UPDATE_COMMAND_UI(ID_PLAY_RESETRATE, OnUpdatePlayResetRate)
318 ON_COMMAND_RANGE(ID_PLAY_INCAUDDELAY, ID_PLAY_DECAUDDELAY, OnPlayChangeAudDelay)
319 ON_UPDATE_COMMAND_UI_RANGE(ID_PLAY_INCAUDDELAY, ID_PLAY_DECAUDDELAY, OnUpdatePlayChangeAudDelay)
320 ON_COMMAND_RANGE(ID_FILTERS_SUBITEM_START, ID_FILTERS_SUBITEM_END, OnPlayFilters)
321 ON_UPDATE_COMMAND_UI_RANGE(ID_FILTERS_SUBITEM_START, ID_FILTERS_SUBITEM_END, OnUpdatePlayFilters)
322 ON_COMMAND_RANGE(ID_SHADERS_START, ID_SHADERS_END, OnPlayShaders)
323 ON_UPDATE_COMMAND_UI_RANGE(ID_SHADERS_START, ID_SHADERS_END, OnUpdatePlayShaders)
324 ON_COMMAND_RANGE(ID_AUDIO_SUBITEM_START, ID_AUDIO_SUBITEM_END, OnPlayAudio)
325 ON_UPDATE_COMMAND_UI_RANGE(ID_AUDIO_SUBITEM_START, ID_AUDIO_SUBITEM_END, OnUpdatePlayAudio)
326 ON_COMMAND_RANGE(ID_SUBTITLES_SUBITEM_START, ID_SUBTITLES_SUBITEM_END, OnPlaySubtitles)
327 ON_UPDATE_COMMAND_UI_RANGE(ID_SUBTITLES_SUBITEM_START, ID_SUBTITLES_SUBITEM_END, OnUpdatePlaySubtitles)
328 ON_COMMAND_RANGE(ID_FILTERSTREAMS_SUBITEM_START, ID_FILTERSTREAMS_SUBITEM_END, OnPlayLanguage)
329 ON_UPDATE_COMMAND_UI_RANGE(ID_FILTERSTREAMS_SUBITEM_START, ID_FILTERSTREAMS_SUBITEM_END, OnUpdatePlayLanguage)
330 ON_COMMAND_RANGE(ID_VOLUME_UP, ID_VOLUME_MUTE, OnPlayVolume)
331 ON_COMMAND_RANGE(ID_VOLUME_BOOST_INC, ID_VOLUME_BOOST_MAX, OnPlayVolumeBoost)
332 ON_UPDATE_COMMAND_UI_RANGE(ID_VOLUME_BOOST_INC, ID_VOLUME_BOOST_MAX, OnUpdatePlayVolumeBoost)
333 ON_COMMAND_RANGE(ID_AFTERPLAYBACK_CLOSE, ID_AFTERPLAYBACK_DONOTHING, OnAfterplayback)
334 ON_UPDATE_COMMAND_UI_RANGE(ID_AFTERPLAYBACK_CLOSE, ID_AFTERPLAYBACK_DONOTHING, OnUpdateAfterplayback)
336 ON_COMMAND_RANGE(ID_NAVIGATE_SKIPBACK, ID_NAVIGATE_SKIPFORWARD, OnNavigateSkip)
337 ON_UPDATE_COMMAND_UI_RANGE(ID_NAVIGATE_SKIPBACK, ID_NAVIGATE_SKIPFORWARD, OnUpdateNavigateSkip)
338 ON_COMMAND_RANGE(ID_NAVIGATE_SKIPBACKPLITEM, ID_NAVIGATE_SKIPFORWARDPLITEM, OnNavigateSkipPlaylistItem)
339 ON_UPDATE_COMMAND_UI_RANGE(ID_NAVIGATE_SKIPBACKPLITEM, ID_NAVIGATE_SKIPFORWARDPLITEM, OnUpdateNavigateSkipPlaylistItem)
340 ON_COMMAND_RANGE(ID_NAVIGATE_TITLEMENU, ID_NAVIGATE_CHAPTERMENU, OnNavigateMenu)
341 ON_UPDATE_COMMAND_UI_RANGE(ID_NAVIGATE_TITLEMENU, ID_NAVIGATE_CHAPTERMENU, OnUpdateNavigateMenu)
342 ON_COMMAND_RANGE(ID_NAVIGATE_AUDIO_SUBITEM_START, ID_NAVIGATE_AUDIO_SUBITEM_END, OnNavigateAudio)
343 ON_COMMAND_RANGE(ID_NAVIGATE_SUBP_SUBITEM_START, ID_NAVIGATE_SUBP_SUBITEM_END, OnNavigateSubpic)
344 ON_COMMAND_RANGE(ID_NAVIGATE_ANGLE_SUBITEM_START, ID_NAVIGATE_ANGLE_SUBITEM_END, OnNavigateAngle)
345 ON_COMMAND_RANGE(ID_NAVIGATE_CHAP_SUBITEM_START, ID_NAVIGATE_CHAP_SUBITEM_END, OnNavigateChapters)
346 ON_COMMAND_RANGE(ID_NAVIGATE_MENU_LEFT, ID_NAVIGATE_MENU_LEAVE, OnNavigateMenuItem)
347 ON_UPDATE_COMMAND_UI_RANGE(ID_NAVIGATE_MENU_LEFT, ID_NAVIGATE_MENU_LEAVE, OnUpdateNavigateMenuItem)
349 ON_COMMAND(ID_FAVORITES_ADD, OnFavoritesAdd)
350 ON_UPDATE_COMMAND_UI(ID_FAVORITES_ADD, OnUpdateFavoritesAdd)
351 ON_COMMAND(ID_FAVORITES_ORGANIZE, OnFavoritesOrganize)
352 ON_UPDATE_COMMAND_UI(ID_FAVORITES_ORGANIZE, OnUpdateFavoritesOrganize)
353 ON_COMMAND_RANGE(ID_FAVORITES_FILE_START, ID_FAVORITES_FILE_END, OnFavoritesFile)
354 ON_UPDATE_COMMAND_UI_RANGE(ID_FAVORITES_FILE_START, ID_FAVORITES_FILE_END, OnUpdateFavoritesFile)
355 ON_COMMAND_RANGE(ID_FAVORITES_DVD_START, ID_FAVORITES_DVD_END, OnFavoritesDVD)
356 ON_UPDATE_COMMAND_UI_RANGE(ID_FAVORITES_DVD_START, ID_FAVORITES_DVD_END, OnUpdateFavoritesDVD)
357 ON_COMMAND_RANGE(ID_FAVORITES_DEVICE_START, ID_FAVORITES_DEVICE_END, OnFavoritesDevice)
358 ON_UPDATE_COMMAND_UI_RANGE(ID_FAVORITES_DEVICE_START, ID_FAVORITES_DEVICE_END, OnUpdateFavoritesDevice)
360 ON_COMMAND(ID_HELP_HOMEPAGE, OnHelpHomepage)
361 ON_COMMAND(ID_HELP_DOCUMENTATION, OnHelpDocumentation)
363 END_MESSAGE_MAP()
365 /////////////////////////////////////////////////////////////////////////////
366 // CMainFrame construction/destruction
368 #pragma warning(disable : 4355)
370 CMainFrame::CMainFrame() :
371 m_dwRegister(0),
372 m_iMediaLoadState(MLS_CLOSED),
373 m_iPlaybackMode(PM_NONE),
374 m_iSpeedLevel(0),
375 m_rtDurationOverride(-1),
376 m_fFullScreen(false),
377 m_fHideCursor(false),
378 m_lastMouseMove(-1, -1),
379 m_pLastBar(NULL),
380 m_nLoops(0),
381 m_iSubtitleSel(-1),
382 m_ZoomX(1), m_ZoomY(1), m_PosX(0.5), m_PosY(0.5),
383 m_AngleX(0), m_AngleY(0), m_AngleZ(0),
384 m_fCustomGraph(false),
385 m_fRealMediaGraph(false), m_fShockwaveGraph(false), m_fQuicktimeGraph(false),
386 m_fFrameSteppingActive(false),
387 m_fEndOfStream(false),
388 m_fCapturing(false),
389 m_fLiveWM(false),
390 m_fOpeningAborted(false),
391 m_fBuffering(false),
392 m_fileDropTarget(this),
393 m_fTrayIcon(false)
397 CMainFrame::~CMainFrame()
399 // m_owner.DestroyWindow();
402 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
404 if(__super::OnCreate(lpCreateStruct) == -1)
405 return -1;
407 m_popup.LoadMenu(IDR_POPUP);
408 m_popupmain.LoadMenu(IDR_POPUPMAIN);
410 GetMenu()->ModifyMenu(ID_FAVORITES, MF_BYCOMMAND|MF_STRING, IDR_MAINFRAME, ResStr(IDS_FAVORITES_POPUP));
412 // create a view to occupy the client area of the frame
413 if(!m_wndView.Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,
414 CRect(0, 0, 0, 0), this, AFX_IDW_PANE_FIRST, NULL))
416 TRACE0("Failed to create view window\n");
417 return -1;
420 // static bars
422 if(!m_wndStatusBar.Create(this)
423 || !m_wndStatsBar.Create(this)
424 || !m_wndInfoBar.Create(this)
425 || !m_wndToolBar.Create(this)
426 || !m_wndSeekBar.Create(this))
428 TRACE0("Failed to create all control bars\n");
429 return -1; // fail to create
432 m_bars.AddTail(&m_wndSeekBar);
433 m_bars.AddTail(&m_wndToolBar);
434 m_bars.AddTail(&m_wndInfoBar);
435 m_bars.AddTail(&m_wndStatsBar);
436 m_bars.AddTail(&m_wndStatusBar);
438 m_wndSeekBar.Enable(false);
440 // dockable bars
442 EnableDocking(CBRS_ALIGN_ANY);
444 m_dockingbars.RemoveAll();
446 m_wndSubresyncBar.Create(this, &m_csSubLock);
447 m_wndSubresyncBar.SetBarStyle(m_wndSubresyncBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
448 m_wndSubresyncBar.EnableDocking(CBRS_ALIGN_ANY);
449 m_wndSubresyncBar.SetHeight(200);
450 LoadControlBar(&m_wndSubresyncBar, AFX_IDW_DOCKBAR_TOP);
452 m_wndPlaylistBar.Create(this);
453 m_wndPlaylistBar.SetBarStyle(m_wndPlaylistBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
454 m_wndPlaylistBar.EnableDocking(CBRS_ALIGN_ANY);
455 m_wndPlaylistBar.SetHeight(100);
456 LoadControlBar(&m_wndPlaylistBar, AFX_IDW_DOCKBAR_BOTTOM);
457 m_wndPlaylistBar.LoadPlaylist();
459 m_wndCaptureBar.Create(this);
460 m_wndCaptureBar.SetBarStyle(m_wndCaptureBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
461 m_wndCaptureBar.EnableDocking(CBRS_ALIGN_LEFT|CBRS_ALIGN_RIGHT);
462 LoadControlBar(&m_wndCaptureBar, AFX_IDW_DOCKBAR_LEFT);
464 m_wndShaderEditorBar.Create(this);
465 m_wndShaderEditorBar.SetBarStyle(m_wndShaderEditorBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
466 m_wndShaderEditorBar.EnableDocking(CBRS_ALIGN_ANY);
467 LoadControlBar(&m_wndShaderEditorBar, AFX_IDW_DOCKBAR_TOP);
469 m_fileDropTarget.Register(this);
471 GetDesktopWindow()->GetWindowRect(&m_rcDesktop);
473 AppSettings& s = AfxGetAppSettings();
475 ShowControls(s.nCS);
477 SetAlwaysOnTop(s.iOnTop);
479 ShowTrayIcon(s.fTrayIcon);
481 SetFocus();
483 m_pGraphThread = (CGraphThread*)AfxBeginThread(RUNTIME_CLASS(CGraphThread));
485 if(m_pGraphThread)
486 m_pGraphThread->SetMainFrame(this);
488 if(s.fEnableWebServer)
489 StartWebServer(s.nWebServerPort);
491 // load shaders
492 CString strList = AfxGetAppSettings().strShaderList;
493 CString strRes;
494 int curPos= 0;
496 strRes = strList.Tokenize (_T("|"), curPos);
497 while (strRes != _T(""))
499 m_shaderlabels.AddTail (strRes);
500 strRes = strList.Tokenize(_T("|"),curPos);
502 // end
505 return 0;
508 void CMainFrame::OnDestroy()
510 ShowTrayIcon(false);
512 m_fileDropTarget.Revoke();
514 if(m_pGraphThread)
516 CAMEvent e;
517 m_pGraphThread->PostThreadMessage(CGraphThread::TM_EXIT, 0, (LPARAM)&e);
518 if(!e.Wait(5000))
520 TRACE(_T("ERROR: Must call TerminateThread() on CMainFrame::m_pGraphThread->m_hThread\n"));
521 TerminateThread(m_pGraphThread->m_hThread, -1);
525 __super::OnDestroy();
528 void CMainFrame::OnClose()
530 // save shader list
531 POSITION pos;
532 CString strList = "";
534 pos = m_shaderlabels.GetHeadPosition();
535 while(pos)
537 strList += m_shaderlabels.GetAt (pos) + "|";
538 m_dockingbars.GetNext(pos);
540 AfxGetAppSettings().strShaderList = strList;
541 // end
543 m_wndPlaylistBar.SavePlaylist();
545 SaveControlBars();
547 ShowWindow(SW_HIDE);
549 CloseMedia();
551 __super::OnClose();
554 DROPEFFECT CMainFrame::OnDragEnter(COleDataObject* pDataObject, DWORD dwKeyState, CPoint point)
556 return DROPEFFECT_NONE;
558 DROPEFFECT CMainFrame::OnDragOver(COleDataObject* pDataObject, DWORD dwKeyState, CPoint point)
560 UINT CF_URL = RegisterClipboardFormat(_T("UniformResourceLocator"));
561 return pDataObject->IsDataAvailable(CF_URL) ? DROPEFFECT_COPY : DROPEFFECT_NONE;
563 BOOL CMainFrame::OnDrop(COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point)
565 UINT CF_URL = RegisterClipboardFormat(_T("UniformResourceLocator"));
567 BOOL bResult = FALSE;
569 if(pDataObject->IsDataAvailable(CF_URL))
571 FORMATETC fmt = {CF_URL, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
572 if(HGLOBAL hGlobal = pDataObject->GetGlobalData(CF_URL, &fmt))
574 LPCSTR pText = (LPCSTR)GlobalLock(hGlobal);
575 if(AfxIsValidString(pText))
577 CStringA url(pText);
579 SetForegroundWindow();
581 CAtlList<CString> sl;
582 sl.AddTail(CString(url));
584 if(m_wndPlaylistBar.IsWindowVisible())
586 m_wndPlaylistBar.Append(sl, true);
588 else
590 m_wndPlaylistBar.Open(sl, true);
591 OpenCurPlaylistItem();
594 GlobalUnlock(hGlobal);
595 bResult = TRUE;
600 return bResult;
602 DROPEFFECT CMainFrame::OnDropEx(COleDataObject* pDataObject, DROPEFFECT dropDefault, DROPEFFECT dropList, CPoint point)
604 return (DROPEFFECT)-1;
606 void CMainFrame::OnDragLeave()
609 DROPEFFECT CMainFrame::OnDragScroll(DWORD dwKeyState, CPoint point)
611 return DROPEFFECT_NONE;
614 void CMainFrame::LoadControlBar(CControlBar* pBar, UINT defDockBarID)
616 if(!pBar) return;
618 CString str;
619 pBar->GetWindowText(str);
620 if(str.IsEmpty()) return;
621 CString section = _T("ToolBars\\") + str;
623 CWinApp* pApp = AfxGetApp();
625 UINT nID = pApp->GetProfileInt(section, _T("DockState"), defDockBarID);
627 if(nID != AFX_IDW_DOCKBAR_FLOAT)
629 DockControlBar(pBar, nID);
632 pBar->ShowWindow(
633 pApp->GetProfileInt(section, _T("Visible"), FALSE)
634 && pBar != &m_wndSubresyncBar
635 && pBar != &m_wndCaptureBar
636 && pBar != &m_wndShaderEditorBar
637 ? SW_SHOW
638 : SW_HIDE);
640 if(CSizingControlBar* pSCB = dynamic_cast<CSizingControlBar*>(pBar))
642 pSCB->LoadState(section + _T("\\State"));
643 m_dockingbars.AddTail(pSCB);
647 void CMainFrame::RestoreFloatingControlBars()
649 CWinApp* pApp = AfxGetApp();
651 CRect r;
652 GetWindowRect(r);
654 POSITION pos = m_dockingbars.GetHeadPosition();
655 while(pos)
657 CSizingControlBar* pBar = m_dockingbars.GetNext(pos);
659 CString str;
660 pBar->GetWindowText(str);
661 if(str.IsEmpty()) return;
662 CString section = _T("ToolBars\\") + str;
664 if(pApp->GetProfileInt(section, _T("DockState"), AFX_IDW_DOCKBAR_FLOAT) == AFX_IDW_DOCKBAR_FLOAT)
666 CPoint p;
667 p.x = pApp->GetProfileInt(section, _T("DockPosX"), 100);
668 p.y = pApp->GetProfileInt(section, _T("DockPosY"), 100);
669 if(p.x < m_rcDesktop.left) p.x = m_rcDesktop.left;
670 if(p.y < m_rcDesktop.top) p.y = m_rcDesktop.top;
671 if(p.x >= m_rcDesktop.right) p.x = m_rcDesktop.right-1;
672 if(p.y >= m_rcDesktop.bottom) p.y = m_rcDesktop.bottom-1;
673 FloatControlBar(pBar, p);
678 void CMainFrame::SaveControlBars()
680 CWinApp* pApp = AfxGetApp();
682 POSITION pos = m_dockingbars.GetHeadPosition();
683 while(pos)
685 CSizingControlBar* pBar = m_dockingbars.GetNext(pos);
687 CString str;
688 pBar->GetWindowText(str);
689 if(str.IsEmpty()) return;
690 CString section = _T("ToolBars\\") + str;
692 pApp->WriteProfileInt(section, _T("Visible"), pBar->IsWindowVisible());
694 if(CSizingControlBar* pSCB = dynamic_cast<CSizingControlBar*>(pBar))
696 pSCB->SaveState(section + _T("\\State"));
699 UINT nID = pBar->GetParent()->GetDlgCtrlID();
701 if(nID == AFX_IDW_DOCKBAR_FLOAT)
703 CRect r;
704 pBar->GetParent()->GetParent()->GetWindowRect(r);
705 pApp->WriteProfileInt(section, _T("DockPosX"), r.left);
706 pApp->WriteProfileInt(section, _T("DockPosY"), r.top);
709 pApp->WriteProfileInt(section, _T("DockState"), nID);
713 LRESULT CMainFrame::OnTaskBarRestart(WPARAM, LPARAM)
715 m_fTrayIcon = false;
716 ShowTrayIcon(AfxGetAppSettings().fTrayIcon);
718 return 0;
721 LRESULT CMainFrame::OnNotifyIcon(WPARAM wParam, LPARAM lParam)
723 if((UINT)wParam != IDR_MAINFRAME)
724 return -1;
726 switch((UINT)lParam)
728 case WM_LBUTTONDOWN:
729 ShowWindow(SW_SHOW);
730 MoveVideoWindow();
731 SetForegroundWindow();
732 break;
734 case WM_LBUTTONDBLCLK:
735 PostMessage(WM_COMMAND, ID_FILE_OPENMEDIA);
736 break;
738 case WM_RBUTTONDOWN:
740 POINT p;
741 GetCursorPos(&p);
742 SetForegroundWindow();
743 m_popupmain.GetSubMenu(0)->TrackPopupMenu(TPM_RIGHTBUTTON|TPM_NOANIMATION, p.x, p.y, this);
744 PostMessage(WM_NULL);
745 break;
748 case WM_MOUSEMOVE:
750 CString str;
751 GetWindowText(str);
752 SetTrayTip(str);
753 break;
756 default:
757 break;
760 return 0;
763 void CMainFrame::ShowTrayIcon(bool fShow)
765 BOOL bWasVisible = ShowWindow(SW_HIDE);
766 NOTIFYICONDATA tnid;
768 ZeroMemory(&tnid, sizeof(NOTIFYICONDATA));
769 tnid.cbSize = sizeof(NOTIFYICONDATA);
770 tnid.hWnd = m_hWnd;
771 tnid.uID = IDR_MAINFRAME;
773 if(fShow)
775 if(!m_fTrayIcon)
777 tnid.hIcon = (HICON)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
778 tnid.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP;
779 tnid.uCallbackMessage = WM_NOTIFYICON;
780 lstrcpyn(tnid.szTip, TEXT("Media Player Classic"), sizeof(tnid.szTip));
781 Shell_NotifyIcon(NIM_ADD, &tnid);
783 m_fTrayIcon = true;
786 else
788 if(m_fTrayIcon)
790 Shell_NotifyIcon(NIM_DELETE, &tnid);
792 m_fTrayIcon = false;
796 if(bWasVisible)
797 ShowWindow(SW_SHOW);
800 void CMainFrame::SetTrayTip(CString str)
802 NOTIFYICONDATA tnid;
803 tnid.cbSize = sizeof(NOTIFYICONDATA);
804 tnid.hWnd = m_hWnd;
805 tnid.uID = IDR_MAINFRAME;
806 tnid.uFlags = NIF_TIP;
807 lstrcpyn(tnid.szTip, str, sizeof(tnid.szTip));
808 Shell_NotifyIcon(NIM_MODIFY, &tnid);
811 BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
813 if(!__super::PreCreateWindow(cs))
814 return FALSE;
816 cs.dwExStyle &= ~WS_EX_CLIENTEDGE;
817 cs.lpszClass = MPC_WND_CLASS_NAME; //AfxRegisterWndClass(0);
819 return TRUE;
822 BOOL CMainFrame::PreTranslateMessage(MSG* pMsg)
824 if(pMsg->message == WM_KEYDOWN)
826 /* if(m_fShockwaveGraph
827 && (pMsg->wParam == VK_LEFT || pMsg->wParam == VK_RIGHT
828 || pMsg->wParam == VK_UP || pMsg->wParam == VK_DOWN))
829 return FALSE;
831 if(pMsg->wParam == VK_ESCAPE && m_iMediaLoadState == MLS_LOADED && m_fFullScreen)
833 OnViewFullscreen();
834 PostMessage(WM_COMMAND, ID_PLAY_PAUSE);
835 return TRUE;
837 else if(pMsg->wParam == VK_ESCAPE && (IsCaptionMenuHidden()))
839 PostMessage(WM_COMMAND, ID_VIEW_CAPTIONMENU);
840 return TRUE;
842 else if(pMsg->wParam == VK_LEFT && pAMTuner)
844 PostMessage(WM_COMMAND, ID_NAVIGATE_SKIPBACK);
845 return TRUE;
847 else if(pMsg->wParam == VK_RIGHT && pAMTuner)
849 PostMessage(WM_COMMAND, ID_NAVIGATE_SKIPFORWARD);
850 return TRUE;
854 return __super::PreTranslateMessage(pMsg);
857 void CMainFrame::RecalcLayout(BOOL bNotify)
859 __super::RecalcLayout(bNotify);
861 CRect r;
862 GetWindowRect(&r);
863 MINMAXINFO mmi;
864 memset(&mmi, 0, sizeof(mmi));
865 SendMessage(WM_GETMINMAXINFO, 0, (LPARAM)&mmi);
866 r |= CRect(r.TopLeft(), CSize(r.Width(), mmi.ptMinTrackSize.y));
867 MoveWindow(&r);
870 /////////////////////////////////////////////////////////////////////////////
871 // CMainFrame diagnostics
873 #ifdef _DEBUG
874 void CMainFrame::AssertValid() const
876 __super::AssertValid();
879 void CMainFrame::Dump(CDumpContext& dc) const
881 __super::Dump(dc);
884 #endif //_DEBUG
886 /////////////////////////////////////////////////////////////////////////////
887 // CMainFrame message handlers
888 void CMainFrame::OnSetFocus(CWnd* pOldWnd)
890 SetAlwaysOnTop(AfxGetAppSettings().iOnTop);
892 // forward focus to the view window
893 if(IsWindow(m_wndView.m_hWnd))
894 m_wndView.SetFocus();
897 BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
899 // let the view have first crack at the command
900 if(m_wndView.OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
901 return TRUE;
903 POSITION pos = m_bars.GetHeadPosition();
904 while(pos)
906 if(m_bars.GetNext(pos)->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
907 return TRUE;
910 pos = m_dockingbars.GetHeadPosition();
911 while(pos)
913 if(m_dockingbars.GetNext(pos)->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
914 return TRUE;
917 // otherwise, do default handling
918 return __super::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
921 void CMainFrame::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
923 DWORD style = GetStyle();
925 MENUBARINFO mbi;
926 memset(&mbi, 0, sizeof(mbi));
927 mbi.cbSize = sizeof(mbi);
928 ::GetMenuBarInfo(m_hWnd, OBJID_MENU, 0, &mbi);
930 lpMMI->ptMinTrackSize.x = 0;
931 if(!IsCaptionMenuHidden())
933 lpMMI->ptMinTrackSize.x = 10;
934 CRect r;
935 for(int i = 0; ::GetMenuItemRect(m_hWnd, mbi.hMenu, i, &r); i++)
936 lpMMI->ptMinTrackSize.x += r.Width();
937 lpMMI->ptMinTrackSize.x = max(DEFCLIENTW, lpMMI->ptMinTrackSize.x);
939 if(style&WS_THICKFRAME) lpMMI->ptMinTrackSize.x += GetSystemMetrics((style&WS_CAPTION)?SM_CXSIZEFRAME:SM_CXFIXEDFRAME)*2;
941 memset(&mbi, 0, sizeof(mbi));
942 mbi.cbSize = sizeof(mbi);
943 ::GetMenuBarInfo(m_hWnd, OBJID_MENU, 0, &mbi);
945 lpMMI->ptMinTrackSize.y = 0;
946 if(style&WS_CAPTION) lpMMI->ptMinTrackSize.y += GetSystemMetrics(SM_CYCAPTION);
947 if(style&WS_THICKFRAME) lpMMI->ptMinTrackSize.y += GetSystemMetrics((style&WS_CAPTION)?SM_CYSIZEFRAME:SM_CYFIXEDFRAME)*2;
948 lpMMI->ptMinTrackSize.y += (mbi.rcBar.bottom - mbi.rcBar.top);
949 if(!AfxGetAppSettings().fHideCaptionMenu) lpMMI->ptMinTrackSize.y += 3;
951 POSITION pos = m_bars.GetHeadPosition();
952 while(pos)
954 CControlBar* pCB = m_bars.GetNext(pos);
955 if(!IsWindow(pCB->m_hWnd) || !pCB->IsVisible()) continue;
957 lpMMI->ptMinTrackSize.y += pCB->CalcFixedLayout(TRUE, TRUE).cy;
960 pos = m_dockingbars.GetHeadPosition();
961 while(pos)
963 CSizingControlBar* pCB = m_dockingbars.GetNext(pos);
964 if(IsWindow(pCB->m_hWnd) && pCB->IsWindowVisible() && !pCB->IsFloating())
965 lpMMI->ptMinTrackSize.y += pCB->CalcFixedLayout(TRUE, TRUE).cy-2;
968 __super::OnGetMinMaxInfo(lpMMI);
971 void CMainFrame::OnMove(int x, int y)
973 __super::OnMove(x, y);
975 MoveVideoWindow();
977 WINDOWPLACEMENT wp;
978 GetWindowPlacement(&wp);
979 if(!m_fFullScreen && wp.flags != WPF_RESTORETOMAXIMIZED && wp.showCmd != SW_SHOWMINIMIZED)
980 GetWindowRect(AfxGetAppSettings().rcLastWindowPos);
983 void CMainFrame::OnMoving(UINT fwSide, LPRECT pRect)
985 __super::OnMoving(fwSide, pRect);
987 if(AfxGetAppSettings().fSnapToDesktopEdges)
989 const CPoint threshold(3, 3);
991 CRect r0 = m_rcDesktop;
992 CRect r1 = r0 + threshold;
993 CRect r2 = r0 - threshold;
995 RECT& wr = *pRect;
996 CSize ws = CRect(wr).Size();
998 if(wr.left < r1.left && wr.left > r2.left)
999 wr.right = (wr.left = r0.left) + ws.cx;
1001 if(wr.top < r1.top && wr.top > r2.top)
1002 wr.bottom = (wr.top = r0.top) + ws.cy;
1004 if(wr.right < r1.right && wr.right > r2.right)
1005 wr.left = (wr.right = r0.right) - ws.cx;
1007 if(wr.bottom < r1.bottom && wr.bottom > r2.bottom)
1008 wr.top = (wr.bottom = r0.bottom) - ws.cy;
1012 void CMainFrame::OnSize(UINT nType, int cx, int cy)
1014 __super::OnSize(nType, cx, cy);
1016 if(nType == SIZE_RESTORED && m_fTrayIcon)
1018 ShowWindow(SW_SHOW);
1021 if(!m_fFullScreen)
1023 AppSettings& s = AfxGetAppSettings();
1024 if(nType != SIZE_MAXIMIZED && nType != SIZE_MINIMIZED)
1025 GetWindowRect(s.rcLastWindowPos);
1026 s.lastWindowType = nType;
1030 void CMainFrame::OnSizing(UINT fwSide, LPRECT pRect)
1032 __super::OnSizing(fwSide, pRect);
1034 AppSettings& s = AfxGetAppSettings();
1036 bool fCtrl = !!(GetAsyncKeyState(VK_CONTROL)&0x80000000);
1038 if(m_iMediaLoadState != MLS_LOADED || m_fFullScreen
1039 || s.iDefaultVideoSize == DVS_STRETCH
1040 || (fCtrl ^ s.fFreeWindowResizing))
1041 return;
1043 CSize wsize(pRect->right - pRect->left, pRect->bottom - pRect->top);
1044 CSize vsize = GetVideoSize();
1045 CSize fsize(0, 0);
1047 if(!vsize.cx || !vsize.cy)
1048 return;
1050 // TODO
1052 DWORD style = GetStyle();
1054 MENUBARINFO mbi;
1055 memset(&mbi, 0, sizeof(mbi));
1056 mbi.cbSize = sizeof(mbi);
1057 ::GetMenuBarInfo(m_hWnd, OBJID_MENU, 0, &mbi);
1059 fsize.cx += GetSystemMetrics((style&WS_CAPTION)?SM_CXSIZEFRAME:SM_CXFIXEDFRAME)*2;
1061 if(style&WS_CAPTION) fsize.cy += GetSystemMetrics(SM_CYCAPTION);
1062 if(style&WS_THICKFRAME) fsize.cy += GetSystemMetrics((style&WS_CAPTION)?SM_CYSIZEFRAME:SM_CYFIXEDFRAME)*2;
1063 fsize.cy += mbi.rcBar.bottom - mbi.rcBar.top;
1064 if(!AfxGetAppSettings().fHideCaptionMenu) fsize.cy += 3;
1066 POSITION pos = m_bars.GetHeadPosition();
1067 while(pos)
1069 CControlBar* pCB = m_bars.GetNext(pos);
1070 if(IsWindow(pCB->m_hWnd) && pCB->IsVisible())
1071 fsize.cy += pCB->CalcFixedLayout(TRUE, TRUE).cy;
1074 pos = m_dockingbars.GetHeadPosition();
1075 while(pos)
1077 CSizingControlBar* pCB = m_dockingbars.GetNext(pos);
1079 if(IsWindow(pCB->m_hWnd) && pCB->IsWindowVisible())
1081 if(pCB->IsHorzDocked()) fsize.cy += pCB->CalcFixedLayout(TRUE, TRUE).cy-2;
1082 else if(pCB->IsVertDocked()) fsize.cx += pCB->CalcFixedLayout(TRUE, FALSE).cx;
1087 wsize -= fsize;
1089 bool fWider = wsize.cy < wsize.cx;
1091 wsize.SetSize(
1092 wsize.cy * vsize.cx / vsize.cy,
1093 wsize.cx * vsize.cy / vsize.cx);
1095 wsize += fsize;
1097 if(fwSide == WMSZ_TOP || fwSide == WMSZ_BOTTOM || !fWider && (fwSide == WMSZ_TOPRIGHT || fwSide == WMSZ_BOTTOMRIGHT))
1099 pRect->right = pRect->left + wsize.cx;
1101 else if(fwSide == WMSZ_LEFT || fwSide == WMSZ_RIGHT || fWider && (fwSide == WMSZ_BOTTOMLEFT || fwSide == WMSZ_BOTTOMRIGHT))
1103 pRect->bottom = pRect->top + wsize.cy;
1105 else if(!fWider && (fwSide == WMSZ_TOPLEFT || fwSide == WMSZ_BOTTOMLEFT))
1107 pRect->left = pRect->right - wsize.cx;
1109 else if(fWider && (fwSide == WMSZ_TOPLEFT || fwSide == WMSZ_TOPRIGHT))
1111 pRect->top = pRect->bottom - wsize.cy;
1115 void CMainFrame::OnDisplayChange() // untested, not sure if it's working...
1117 TRACE(_T("*** CMainFrame::OnDisplayChange()\n"));
1119 if(m_iMediaLoadState == MLS_LOADED && m_pCAP)
1120 m_pCAP->OnDisplayChange();
1123 GetDesktopWindow()->GetWindowRect(&m_rcDesktop);
1126 #include <psapi.h>
1128 void CMainFrame::OnSysCommand(UINT nID, LPARAM lParam)
1130 if( (GetMediaState() == State_Running) && (((nID & 0xFFF0) == SC_SCREENSAVE) || ((nID & 0xFFF0) == SC_MONITORPOWER)) )
1132 TRACE(_T("SC_SCREENSAVE, nID = %d, lParam = %d\n"), nID, lParam);
1133 return;
1135 else if((nID & 0xFFF0) == SC_MINIMIZE && m_fTrayIcon)
1137 ShowWindow(SW_HIDE);
1138 return;
1141 __super::OnSysCommand(nID, lParam);
1144 void CMainFrame::OnActivateApp(BOOL bActive, DWORD dwThreadID)
1146 __super::OnActivateApp(bActive, dwThreadID);
1148 MONITORINFO mi;
1149 mi.cbSize = sizeof(MONITORINFO);
1150 GetMonitorInfo(MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST), &mi);
1152 if(!bActive && (mi.dwFlags&MONITORINFOF_PRIMARY) && m_fFullScreen && m_iMediaLoadState == MLS_LOADED)
1154 bool fExitFullscreen = true;
1156 if(CWnd* pWnd = GetForegroundWindow())
1158 HMONITOR hMonitor1 = MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST);
1159 HMONITOR hMonitor2 = MonitorFromWindow(pWnd->m_hWnd, MONITOR_DEFAULTTONEAREST);
1160 if(hMonitor1 && hMonitor2 && hMonitor1 != hMonitor2) fExitFullscreen = false;
1162 CString title;
1163 pWnd->GetWindowText(title);
1165 CString module;
1167 if(GetVersion()&0x80000000)
1169 module.ReleaseBufferSetLength(GetWindowModuleFileName(pWnd->m_hWnd, module.GetBuffer(MAX_PATH), MAX_PATH));
1171 else
1173 DWORD pid;
1174 GetWindowThreadProcessId(pWnd->m_hWnd, &pid);
1176 if(HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid))
1178 HMODULE hMod;
1179 DWORD cbNeeded;
1181 if(EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded))
1183 module.ReleaseBufferSetLength(GetModuleFileNameEx(hProcess, hMod, module.GetBuffer(MAX_PATH), MAX_PATH));
1186 CloseHandle(hProcess);
1190 CPath p(module);
1191 p.StripPath();
1192 module = (LPCTSTR)p;
1193 module.MakeLower();
1195 CString str;
1196 str.Format(_T("Focus lost to: %s - %s"), module, title);
1197 SendStatusMessage(str, 5000);
1200 if(fExitFullscreen) OnViewFullscreen();
1204 LRESULT CMainFrame::OnAppCommand(WPARAM wParam, LPARAM lParam)
1206 UINT cmd = GET_APPCOMMAND_LPARAM(lParam);
1207 UINT uDevice = GET_DEVICE_LPARAM(lParam);
1208 UINT dwKeys = GET_KEYSTATE_LPARAM(lParam);
1210 if(uDevice != FAPPCOMMAND_OEM)
1212 AppSettings& s = AfxGetAppSettings();
1214 BOOL fRet = FALSE;
1216 POSITION pos = s.wmcmds.GetHeadPosition();
1217 while(pos)
1219 wmcmd& wc = s.wmcmds.GetNext(pos);
1220 if(wc.appcmd == cmd && TRUE == SendMessage(WM_COMMAND, wc.cmd))
1221 fRet = TRUE;
1224 if(fRet) return TRUE;
1227 return Default();
1230 void CMainFrame::OnTimer(UINT nIDEvent)
1232 if(nIDEvent == TIMER_STREAMPOSPOLLER && m_iMediaLoadState == MLS_LOADED)
1234 REFERENCE_TIME rtNow = 0, rtDur = 0;
1236 if(m_iPlaybackMode == PM_FILE)
1238 pMS->GetCurrentPosition(&rtNow);
1239 pMS->GetDuration(&rtDur);
1241 if(m_rtDurationOverride >= 0) rtDur = m_rtDurationOverride;
1243 m_wndSeekBar.Enable(rtDur > 0);
1244 m_wndSeekBar.SetRange(0, rtDur);
1245 m_wndSeekBar.SetPos(rtNow);
1247 else if(m_iPlaybackMode == PM_CAPTURE)
1249 if(m_fCapturing && m_wndCaptureBar.m_capdlg.m_pMux)
1251 CComQIPtr<IMediaSeeking> pMuxMS = m_wndCaptureBar.m_capdlg.m_pMux;
1252 if(!pMuxMS || FAILED(pMuxMS->GetCurrentPosition(&rtNow))) rtNow = 0;
1255 if(m_rtDurationOverride >= 0) rtDur = m_rtDurationOverride;
1257 m_wndSeekBar.Enable(false);
1258 m_wndSeekBar.SetRange(0, rtDur);
1259 m_wndSeekBar.SetPos(rtNow);
1261 if(m_fCapturing)
1263 if(rtNow > 10000i64*1000*60*60*3)
1265 m_wndCaptureBar.m_capdlg.OnRecord();
1271 if(m_pCAP && m_iPlaybackMode != PM_FILE) m_pCAP->SetTime(/*rtNow*/m_wndSeekBar.GetPos());
1273 else if(nIDEvent == TIMER_STREAMPOSPOLLER2 && m_iMediaLoadState == MLS_LOADED)
1275 __int64 start, stop, pos;
1276 m_wndSeekBar.GetRange(start, stop);
1277 pos = m_wndSeekBar.GetPosReal();
1279 GUID tf;
1280 pMS->GetTimeFormat(&tf);
1282 if(m_iPlaybackMode == PM_CAPTURE && !m_fCapturing)
1284 CString str = _T("Live");
1286 long lChannel = 0, lVivSub = 0, lAudSub = 0;
1287 if(pAMTuner
1288 && m_wndCaptureBar.m_capdlg.IsTunerActive()
1289 && SUCCEEDED(pAMTuner->get_Channel(&lChannel, &lVivSub, &lAudSub)))
1291 CString ch;
1292 ch.Format(_T(" (ch%d)"), lChannel);
1293 str += ch;
1296 m_wndStatusBar.SetStatusTimer(str);
1298 else
1300 m_wndStatusBar.SetStatusTimer(pos, stop, !!m_wndSubresyncBar.IsWindowVisible(), &tf);
1303 m_wndSubresyncBar.SetTime(pos);
1305 if(m_pCAP && GetMediaState() == State_Paused) m_pCAP->Paint(true);
1307 else if(nIDEvent == TIMER_FULLSCREENCONTROLBARHIDER)
1309 CPoint p;
1310 GetCursorPos(&p);
1312 CRect r;
1313 GetWindowRect(r);
1314 bool fCursorOutside = !r.PtInRect(p);
1316 CWnd* pWnd = WindowFromPoint(p);
1317 if(pWnd && (m_wndView == *pWnd || m_wndView.IsChild(pWnd) || fCursorOutside))
1319 if(AfxGetAppSettings().nShowBarsWhenFullScreenTimeOut >= 0)
1320 ShowControls(CS_NONE, false);
1323 else if(nIDEvent == TIMER_FULLSCREENMOUSEHIDER)
1325 CPoint p;
1326 GetCursorPos(&p);
1328 CRect r;
1329 GetWindowRect(r);
1330 bool fCursorOutside = !r.PtInRect(p);
1332 CWnd* pWnd = WindowFromPoint(p);
1333 if(pWnd && (m_wndView == *pWnd || m_wndView.IsChild(pWnd) || fCursorOutside))
1335 m_fHideCursor = true;
1336 SetCursor(NULL);
1339 else if(nIDEvent == TIMER_STATS)
1341 if(pQP)
1343 CString rate;
1344 if(m_iSpeedLevel >= -11 && m_iSpeedLevel <= 3 && m_iSpeedLevel != -4)
1346 CString speeds[] = {_T("1/8"),_T("1/4"),_T("1/2"),_T("1"),_T("2"),_T("4"),_T("8")};
1347 rate = speeds[(m_iSpeedLevel >= -3 ? m_iSpeedLevel : (-m_iSpeedLevel - 8)) + 3];
1348 if(m_iSpeedLevel < -4) rate = _T("-") + rate;
1349 if(!rate.IsEmpty()) rate = _T("(") + rate + _T("X)");
1352 CString info;
1353 int val;
1355 pQP->get_AvgFrameRate(&val);
1356 info.Format(_T("%d.%02d %s"), val/100, val%100, rate);
1357 m_wndStatsBar.SetLine(_T("Frame-rate"), info);
1359 int avg, dev;
1360 pQP->get_AvgSyncOffset(&avg);
1361 pQP->get_DevSyncOffset(&dev);
1362 info.Format(_T("avg: %d ms, dev: %d ms"), avg, dev);
1363 m_wndStatsBar.SetLine(_T("Sync Offset"), info);
1365 int drawn, dropped;
1366 pQP->get_FramesDrawn(&drawn);
1367 pQP->get_FramesDroppedInRenderer(&dropped);
1368 info.Format(_T("drawn: %d, dropped: %d"), drawn, dropped);
1369 m_wndStatsBar.SetLine(_T("Frames"), info);
1371 pQP->get_Jitter(&val);
1372 info.Format(_T("%d ms"), val);
1373 m_wndStatsBar.SetLine(_T("Jitter"), info);
1376 if(pBI)
1378 CAtlList<CString> sl;
1380 for(int i = 0, j = pBI->GetCount(); i < j; i++)
1382 int samples, size;
1383 if(S_OK == pBI->GetStatus(i, samples, size))
1385 CString str;
1386 str.Format(_T("[%d]: %03d/%d KB"), i, samples, size / 1024);
1387 sl.AddTail(str);
1391 if(!sl.IsEmpty())
1393 CString str;
1394 str.Format(_T("%s (p%d)"), Implode(sl, ' '), pBI->GetPriority());
1396 m_wndStatsBar.SetLine(_T("Buffers"), str);
1400 CInterfaceList<IBitRateInfo> pBRIs;
1402 BeginEnumFilters(pGB, pEF, pBF)
1404 BeginEnumPins(pBF, pEP, pPin)
1406 if(CComQIPtr<IBitRateInfo> pBRI = pPin)
1408 pBRIs.AddTail(pBRI);
1411 EndEnumPins
1413 if(!pBRIs.IsEmpty())
1415 CAtlList<CString> sl;
1417 POSITION pos = pBRIs.GetHeadPosition();
1418 for(int i = 0; pos; i++)
1420 IBitRateInfo* pBRI = pBRIs.GetNext(pos);
1422 DWORD cur = pBRI->GetCurrentBitRate() / 1000;
1423 DWORD avg = pBRI->GetAverageBitRate() / 1000;
1425 if(avg == 0) continue;
1427 CString str;
1428 if(cur != avg) str.Format(_T("[%d]: %d/%d Kb/s"), i, avg, cur);
1429 else str.Format(_T("[%d]: %d Kb/s"), i, avg);
1430 sl.AddTail(str);
1433 if(!sl.IsEmpty())
1435 m_wndStatsBar.SetLine(_T("Bitrate"), Implode(sl, ' ') + _T(" (avg/cur)"));
1438 break;
1441 EndEnumFilters
1443 if(m_iPlaybackMode == PM_FILE)
1445 SetupChapters();
1448 if(m_iPlaybackMode == PM_DVD) // we also use this timer to update the info panel for dvd playback
1450 ULONG ulAvailable, ulCurrent;
1452 // Location
1454 CString Location('-');
1456 DVD_PLAYBACK_LOCATION2 loc;
1457 ULONG ulNumOfVolumes, ulVolume;
1458 DVD_DISC_SIDE Side;
1459 ULONG ulNumOfTitles;
1460 ULONG ulNumOfChapters;
1462 if(SUCCEEDED(pDVDI->GetCurrentLocation(&loc))
1463 && SUCCEEDED(pDVDI->GetNumberOfChapters(loc.TitleNum, &ulNumOfChapters))
1464 && SUCCEEDED(pDVDI->GetDVDVolumeInfo(&ulNumOfVolumes, &ulVolume, &Side, &ulNumOfTitles)))
1466 Location.Format(_T("Volume: %02d/%02d, Title: %02d/%02d, Chapter: %02d/%02d"),
1467 ulVolume, ulNumOfVolumes,
1468 loc.TitleNum, ulNumOfTitles,
1469 loc.ChapterNum, ulNumOfChapters);
1472 m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_LOCATION), Location);
1474 // Video
1476 CString Video('-');
1478 DVD_VideoAttributes VATR;
1480 if(SUCCEEDED(pDVDI->GetCurrentAngle(&ulAvailable, &ulCurrent))
1481 && SUCCEEDED(pDVDI->GetCurrentVideoAttributes(&VATR)))
1483 Video.Format(_T("Angle: %02d/%02d, %dx%d %dHz %d:%d"),
1484 ulAvailable, ulCurrent,
1485 VATR.ulSourceResolutionX, VATR.ulSourceResolutionY, VATR.ulFrameRate,
1486 VATR.ulAspectX, VATR.ulAspectY);
1489 m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_VIDEO), Video);
1491 // Audio
1493 CString Audio('-');
1495 DVD_AudioAttributes AATR;
1497 if(SUCCEEDED(pDVDI->GetCurrentAudio(&ulAvailable, &ulCurrent))
1498 && SUCCEEDED(pDVDI->GetAudioAttributes(ulCurrent, &AATR)))
1500 CString lang;
1501 int len = GetLocaleInfo(AATR.Language, LOCALE_SENGLANGUAGE, lang.GetBuffer(64), 64);
1502 lang.ReleaseBufferSetLength(max(len-1, 0));
1504 switch(AATR.LanguageExtension)
1506 case DVD_AUD_EXT_NotSpecified:
1507 default: break;
1508 case DVD_AUD_EXT_Captions: lang += _T(" (Captions)"); break;
1509 case DVD_AUD_EXT_VisuallyImpaired: lang += _T(" (Visually Impaired)"); break;
1510 case DVD_AUD_EXT_DirectorComments1: lang += _T(" (Director Comments 1)"); break;
1511 case DVD_AUD_EXT_DirectorComments2: lang += _T(" (Director Comments 2)"); break;
1514 CString format;
1515 switch(AATR.AudioFormat)
1517 case DVD_AudioFormat_AC3: format = _T("AC3"); break;
1518 case DVD_AudioFormat_MPEG1:
1519 case DVD_AudioFormat_MPEG1_DRC: format = _T("MPEG1"); break;
1520 case DVD_AudioFormat_MPEG2:
1521 case DVD_AudioFormat_MPEG2_DRC: format = _T("MPEG2"); break;
1522 case DVD_AudioFormat_LPCM: format = _T("LPCM"); break;
1523 case DVD_AudioFormat_DTS: format = _T("DTS"); break;
1524 case DVD_AudioFormat_SDDS: format = _T("SDDS"); break;
1525 case DVD_AudioFormat_Other:
1526 default: format = _T("Unknown format"); break;
1529 Audio.Format(_T("%s, %s %dHz %dbits %d channel(s)"),
1530 lang,
1531 format,
1532 AATR.dwFrequency,
1533 AATR.bQuantization,
1534 AATR.bNumberOfChannels);
1536 m_wndStatusBar.SetStatusBitmap(
1537 AATR.bNumberOfChannels == 1 ? IDB_MONO
1538 : AATR.bNumberOfChannels >= 2 ? IDB_STEREO
1539 : IDB_NOAUDIO);
1542 m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_AUDIO), Audio);
1544 // Subtitles
1546 CString Subtitles('-');
1548 BOOL bIsDisabled;
1549 DVD_SubpictureAttributes SATR;
1551 if(SUCCEEDED(pDVDI->GetCurrentSubpicture(&ulAvailable, &ulCurrent, &bIsDisabled))
1552 && SUCCEEDED(pDVDI->GetSubpictureAttributes(ulCurrent, &SATR)))
1554 CString lang;
1555 int len = GetLocaleInfo(SATR.Language, LOCALE_SENGLANGUAGE, lang.GetBuffer(64), 64);
1556 lang.ReleaseBufferSetLength(max(len-1, 0));
1558 switch(SATR.LanguageExtension)
1560 case DVD_SP_EXT_NotSpecified:
1561 default: break;
1562 case DVD_SP_EXT_Caption_Normal: lang += _T(""); break;
1563 case DVD_SP_EXT_Caption_Big: lang += _T(" (Big)"); break;
1564 case DVD_SP_EXT_Caption_Children: lang += _T(" (Children)"); break;
1565 case DVD_SP_EXT_CC_Normal: lang += _T(" (CC)"); break;
1566 case DVD_SP_EXT_CC_Big: lang += _T(" (CC Big)"); break;
1567 case DVD_SP_EXT_CC_Children: lang += _T(" (CC Children)"); break;
1568 case DVD_SP_EXT_Forced: lang += _T(" (Forced)"); break;
1569 case DVD_SP_EXT_DirectorComments_Normal: lang += _T(" (Director Comments)"); break;
1570 case DVD_SP_EXT_DirectorComments_Big: lang += _T(" (Director Comments, Big)"); break;
1571 case DVD_SP_EXT_DirectorComments_Children: lang += _T(" (Director Comments, Children)"); break;
1574 if(bIsDisabled) lang = _T("-");
1576 Subtitles.Format(_T("%s"),
1577 lang);
1580 m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_SUBTITLES), Subtitles);
1583 if(GetMediaState() == State_Running)
1585 UINT fSaverActive = 0;
1586 if(SystemParametersInfo(SPI_GETSCREENSAVEACTIVE, 0, (PVOID)&fSaverActive, 0))
1588 SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, 0, 0, SPIF_SENDWININICHANGE); // this might not be needed at all...
1589 SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, fSaverActive, 0, SPIF_SENDWININICHANGE);
1592 fSaverActive = 0;
1593 if(SystemParametersInfo(SPI_GETPOWEROFFACTIVE, 0, (PVOID)&fSaverActive, 0))
1595 SystemParametersInfo(SPI_SETPOWEROFFACTIVE, 0, 0, SPIF_SENDWININICHANGE); // this might not be needed at all...
1596 SystemParametersInfo(SPI_SETPOWEROFFACTIVE, fSaverActive, 0, SPIF_SENDWININICHANGE);
1600 else if(nIDEvent == TIMER_STATUSERASER)
1602 KillTimer(TIMER_STATUSERASER);
1603 m_playingmsg.Empty();
1606 __super::OnTimer(nIDEvent);
1609 static bool SetShutdownPrivilege()
1611 HANDLE hToken;
1612 TOKEN_PRIVILEGES tkp;
1614 // Get a token for this process.
1616 if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
1617 return(false);
1619 // Get the LUID for the shutdown privilege.
1621 LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
1623 tkp.PrivilegeCount = 1; // one privilege to set
1624 tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
1626 // Get the shutdown privilege for this process.
1628 AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
1630 if(GetLastError() != ERROR_SUCCESS)
1631 return false;
1633 return true;
1636 bool CMainFrame::DoAfterPlaybackEvent()
1638 AppSettings& s = AfxGetAppSettings();
1640 bool fExit = false;
1642 if(s.nCLSwitches&CLSW_CLOSE)
1644 fExit = true;
1647 if(s.nCLSwitches&CLSW_STANDBY)
1649 SetShutdownPrivilege();
1650 SetSystemPowerState(TRUE, TRUE);
1651 fExit = true; // TODO: unless the app closes, it will call standby or hibernate once again forever, how to avoid that?
1653 else if(s.nCLSwitches&CLSW_HIBERNATE)
1655 SetShutdownPrivilege();
1656 SetSystemPowerState(FALSE, TRUE);
1657 fExit = true; // TODO: unless the app closes, it will call standby or hibernate once again forever, how to avoid that?
1659 else if(s.nCLSwitches&CLSW_SHUTDOWN)
1661 SetShutdownPrivilege();
1662 ExitWindowsEx(EWX_SHUTDOWN|EWX_POWEROFF|EWX_FORCEIFHUNG, 0);
1663 fExit = true;
1665 else if(s.nCLSwitches&CLSW_LOGOFF)
1667 SetShutdownPrivilege();
1668 ExitWindowsEx(EWX_LOGOFF|EWX_FORCEIFHUNG, 0);
1669 fExit = true;
1672 if(!fExit) return false;
1674 SendMessage(WM_COMMAND, ID_FILE_EXIT);
1676 return true;
1680 // our WM_GRAPHNOTIFY handler
1682 #include <comdef.h>
1683 LRESULT CMainFrame::OnGraphNotify(WPARAM wParam, LPARAM lParam)
1685 HRESULT hr = S_OK;
1687 LONG evCode, evParam1, evParam2;
1688 while(pME && SUCCEEDED(pME->GetEvent(&evCode, (LONG_PTR*)&evParam1, (LONG_PTR*)&evParam2, 0)))
1690 CString str;
1692 if(m_fCustomGraph)
1694 if(EC_BG_ERROR == evCode)
1696 str = CString((char*)evParam1);
1700 hr = pME->FreeEventParams(evCode, evParam1, evParam2);
1702 if(EC_COMPLETE == evCode)
1704 AppSettings& s = AfxGetAppSettings();
1706 if(m_wndPlaylistBar.GetCount() <= 1)
1708 m_nLoops++;
1710 if(DoAfterPlaybackEvent()) return hr;
1712 if(s.fLoopForever || m_nLoops < s.nLoops)
1714 if(GetMediaState() == State_Stopped)
1716 SendMessage(WM_COMMAND, ID_PLAY_PLAY);
1718 else
1720 LONGLONG pos = 0;
1721 pMS->SetPositions(&pos, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning);
1723 if(GetMediaState() == State_Paused)
1725 SendMessage(WM_COMMAND, ID_PLAY_PLAY);
1729 else
1731 if(s.fRewind) SendMessage(WM_COMMAND, ID_PLAY_STOP);
1732 else m_fEndOfStream = true;
1733 SendMessage(WM_COMMAND, ID_PLAY_PAUSE);
1735 if(m_fFullScreen && s.fExitFullScreenAtTheEnd)
1736 OnViewFullscreen();
1739 else if(m_wndPlaylistBar.GetCount() > 1)
1741 if(m_wndPlaylistBar.IsAtEnd())
1743 if(DoAfterPlaybackEvent()) return hr;
1745 m_nLoops++;
1748 if(s.fLoopForever || m_nLoops < s.nLoops)
1750 int nLoops = m_nLoops;
1751 PostMessage(WM_COMMAND, ID_NAVIGATE_SKIPFORWARD);
1752 m_nLoops = nLoops;
1754 else
1756 if(m_fFullScreen && s.fExitFullScreenAtTheEnd)
1757 OnViewFullscreen();
1759 if(s.fRewind)
1761 AfxGetAppSettings().nCLSwitches |= CLSW_OPEN; // HACK
1762 PostMessage(WM_COMMAND, ID_NAVIGATE_SKIPFORWARD);
1764 else
1766 m_fEndOfStream = true;
1767 PostMessage(WM_COMMAND, ID_PLAY_PAUSE);
1772 else if(EC_ERRORABORT == evCode)
1774 TRACE(_T("EC_ERRORABORT, hr = %08x\n"), (HRESULT)evParam1);
1775 // SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
1776 // m_closingmsg = _com_error((HRESULT)evParam1).ErrorMessage();
1778 else if(EC_REPAINT == evCode)
1780 TRACE(_T("EC_REPAINT\n"));
1782 else if(EC_BUFFERING_DATA == evCode)
1784 TRACE(_T("EC_BUFFERING_DATA, %d, %d\n"), (HRESULT)evParam1, evParam2);
1786 m_fBuffering = ((HRESULT)evParam1 != S_OK);
1788 else if(EC_STEP_COMPLETE == evCode)
1790 if(m_fFrameSteppingActive)
1792 m_fFrameSteppingActive = false;
1793 pBA->put_Volume(m_VolumeBeforeFrameStepping);
1796 else if(EC_DEVICE_LOST == evCode)
1798 CComQIPtr<IBaseFilter> pBF;
1799 if(m_iPlaybackMode == PM_CAPTURE
1800 && (!pVidCap && pVidCap == (pBF = (IUnknown*)evParam1)
1801 || !pAudCap && pAudCap == (pBF = (IUnknown*)evParam1))
1802 && evParam2 == 0)
1804 SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
1807 else if(EC_DVD_TITLE_CHANGE == evCode)
1809 if(m_iPlaybackMode == PM_FILE)
1811 SetupChapters();
1813 else if(m_iPlaybackMode == PM_DVD)
1815 m_iDVDTitle = (DWORD)evParam1;
1817 if(m_iDVDDomain == DVD_DOMAIN_Title)
1819 CString Domain;
1820 Domain.Format(_T("Title %d"), m_iDVDTitle);
1821 m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_DOMAIN), Domain);
1825 else if(EC_DVD_DOMAIN_CHANGE == evCode)
1827 m_iDVDDomain = (DVD_DOMAIN)evParam1;
1829 CString Domain('-');
1831 switch(m_iDVDDomain)
1833 case DVD_DOMAIN_FirstPlay: Domain = _T("First Play"); break;
1834 case DVD_DOMAIN_VideoManagerMenu: Domain = _T("Video Manager Menu"); break;
1835 case DVD_DOMAIN_VideoTitleSetMenu: Domain = _T("Video Title Set Menu"); break;
1836 case DVD_DOMAIN_Title: Domain.Format(_T("Title %d"), m_iDVDTitle); break;
1837 case DVD_DOMAIN_Stop: Domain = _T("Stop"); break;
1838 default: Domain = _T("-"); break;
1841 m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_DOMAIN), Domain);
1843 MoveVideoWindow(); // AR might have changed
1845 else if(EC_DVD_CURRENT_HMSF_TIME == evCode)
1847 double fps = evParam2 == DVD_TC_FLAG_25fps ? 25.0
1848 : evParam2 == DVD_TC_FLAG_30fps ? 30.0
1849 : evParam2 == DVD_TC_FLAG_DropFrame ? 29.97
1850 : 25.0;
1852 REFERENCE_TIME rtDur = 0;
1854 DVD_HMSF_TIMECODE tcDur;
1855 ULONG ulFlags;
1856 if(SUCCEEDED(pDVDI->GetTotalTitleTime(&tcDur, &ulFlags)))
1857 rtDur = HMSF2RT(tcDur, fps);
1859 m_wndSeekBar.Enable(rtDur > 0);
1860 m_wndSeekBar.SetRange(0, rtDur);
1862 REFERENCE_TIME rtNow = HMSF2RT(*((DVD_HMSF_TIMECODE*)&evParam1), fps);
1864 m_wndSeekBar.SetPos(rtNow);
1866 if(m_pSubClock) m_pSubClock->SetTime(rtNow);
1868 else if(EC_DVD_ERROR == evCode)
1870 TRACE(_T("EC_DVD_ERROR %d %d\n"), evParam1, evParam2);
1872 CString err;
1874 switch(evParam1)
1876 case DVD_ERROR_Unexpected: default: err = _T("DVD: Unexpected error"); break;
1877 case DVD_ERROR_CopyProtectFail: err = _T("DVD: Copy-Protect Fail"); break;
1878 case DVD_ERROR_InvalidDVD1_0Disc: err = _T("DVD: Invalid DVD 1.x Disc"); break;
1879 case DVD_ERROR_InvalidDiscRegion: err = _T("DVD: Invalid Disc Region"); break;
1880 case DVD_ERROR_LowParentalLevel: err = _T("DVD: Low Parental Level"); break;
1881 case DVD_ERROR_MacrovisionFail: err = _T("DVD: Macrovision Fail"); break;
1882 case DVD_ERROR_IncompatibleSystemAndDecoderRegions: err = _T("DVD: Incompatible System And Decoder Regions"); break;
1883 case DVD_ERROR_IncompatibleDiscAndDecoderRegions: err = _T("DVD: Incompatible Disc And Decoder Regions"); break;
1886 SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
1888 m_closingmsg = err;
1890 else if(EC_DVD_WARNING == evCode)
1892 TRACE(_T("EC_DVD_WARNING %d %d\n"), evParam1, evParam2);
1894 else if(EC_VIDEO_SIZE_CHANGED == evCode)
1896 TRACE(_T("EC_VIDEO_SIZE_CHANGED %dx%d\n"), CSize(evParam1));
1898 WINDOWPLACEMENT wp;
1899 wp.length = sizeof(wp);
1900 GetWindowPlacement(&wp);
1902 CSize size(evParam1);
1903 m_fAudioOnly = (size.cx <= 0 || size.cy <= 0);
1905 if(AfxGetAppSettings().fRememberZoomLevel
1906 && !(m_fFullScreen || wp.showCmd == SW_SHOWMAXIMIZED || wp.showCmd == SW_SHOWMINIMIZED))
1908 ZoomVideoWindow();
1910 else
1912 MoveVideoWindow();
1915 if(m_iMediaLoadState == MLS_LOADED
1916 && !m_fAudioOnly && (AfxGetAppSettings().nCLSwitches&CLSW_FULLSCREEN))
1918 PostMessage(WM_COMMAND, ID_VIEW_FULLSCREEN);
1919 AfxGetAppSettings().nCLSwitches &= ~CLSW_FULLSCREEN;
1922 else if(EC_LENGTH_CHANGED == evCode)
1924 __int64 rtDur = 0;
1925 pMS->GetDuration(&rtDur);
1926 m_wndPlaylistBar.SetCurTime(rtDur);
1928 else if(!m_fCustomGraph)
1930 TRACE(_T("evCode: %d\n"), evCode);
1932 else if(EC_BG_AUDIO_CHANGED == evCode)
1934 int nAudioChannels = evParam1;
1936 m_wndStatusBar.SetStatusBitmap(nAudioChannels == 1 ? IDB_MONO
1937 : nAudioChannels >= 2 ? IDB_STEREO
1938 : IDB_NOAUDIO);
1940 else if(EC_BG_ERROR == evCode)
1942 SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
1943 m_closingmsg = !str.IsEmpty() ? str : _T("Unspecified graph error");
1944 m_wndPlaylistBar.SetCurValid(false);
1945 break;
1949 return hr;
1952 LRESULT CMainFrame::OnRepaintRenderLess(WPARAM wParam, LPARAM lParam)
1954 MoveVideoWindow();
1955 return TRUE;
1958 LRESULT CMainFrame::OnResumeFromState(WPARAM wParam, LPARAM lParam)
1960 int iPlaybackMode = (int)wParam;
1962 if(iPlaybackMode == PM_FILE)
1964 SeekTo(10000i64*int(lParam));
1966 else if(iPlaybackMode == PM_DVD)
1968 CComPtr<IDvdState> pDvdState;
1969 pDvdState.Attach((IDvdState*)lParam);
1970 if(pDVDC) pDVDC->SetState(pDvdState, DVD_CMD_FLAG_Block, NULL);
1972 else if(iPlaybackMode == PM_CAPTURE)
1974 // not implemented
1976 else
1978 ASSERT(0);
1979 return FALSE;
1982 return TRUE;
1985 BOOL CMainFrame::OnButton(UINT id, UINT nFlags, CPoint point)
1987 SetFocus();
1989 CRect r;
1990 m_wndView.GetClientRect(r);
1991 m_wndView.MapWindowPoints(this, &r);
1993 if(id != wmcmd::WDOWN && id != wmcmd::WUP && !r.PtInRect(point)) return FALSE;
1995 BOOL ret = FALSE;
1997 AppSettings& s = AfxGetAppSettings();
1998 POSITION pos = s.wmcmds.GetHeadPosition();
1999 while(pos)
2001 wmcmd& wc = s.wmcmds.GetNext(pos);
2002 if(wc.mouse == id)
2004 SendMessage(WM_COMMAND, wc.cmd);
2005 ret = true;
2009 return ret;
2012 static bool s_fLDown = false;
2014 void CMainFrame::OnLButtonDown(UINT nFlags, CPoint point)
2016 SetFocus();
2018 bool fClicked = false;
2020 if(m_iPlaybackMode == PM_DVD)
2022 CPoint p = point - m_wndView.GetVideoRect().TopLeft();
2024 if(SUCCEEDED(pDVDC->ActivateAtPosition(p))
2025 || m_iDVDDomain == DVD_DOMAIN_VideoManagerMenu
2026 || m_iDVDDomain == DVD_DOMAIN_VideoTitleSetMenu)
2027 fClicked = true;
2030 if(!fClicked)
2032 bool fLeftMouseBtnUnassigned = true;
2033 AppSettings& s = AfxGetAppSettings();
2034 POSITION pos = s.wmcmds.GetHeadPosition();
2035 while(pos && fLeftMouseBtnUnassigned)
2036 if(s.wmcmds.GetNext(pos).mouse == wmcmd::LDOWN)
2037 fLeftMouseBtnUnassigned = false;
2039 if(!m_fFullScreen && (IsCaptionMenuHidden() || fLeftMouseBtnUnassigned))
2041 PostMessage(WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(point.x, point.y));
2043 else
2045 s_fLDown = true;
2046 if(OnButton(wmcmd::LDOWN, nFlags, point))
2047 return;
2051 __super::OnLButtonDown(nFlags, point);
2054 void CMainFrame::OnLButtonUp(UINT nFlags, CPoint point)
2056 if(!OnButton(wmcmd::LUP, nFlags, point))
2057 __super::OnLButtonUp(nFlags, point);
2060 void CMainFrame::OnLButtonDblClk(UINT nFlags, CPoint point)
2062 if(s_fLDown)
2064 SendMessage(WM_LBUTTONDOWN, nFlags, MAKELPARAM(point.x, point.y));
2065 s_fLDown = false;
2067 if(!OnButton(wmcmd::LDBLCLK, nFlags, point))
2068 __super::OnLButtonDblClk(nFlags, point);
2071 void CMainFrame::OnMButtonDown(UINT nFlags, CPoint point)
2073 SendMessage(WM_CANCELMODE);
2074 if(!OnButton(wmcmd::MDOWN, nFlags, point))
2075 __super::OnMButtonDown(nFlags, point);
2078 void CMainFrame::OnMButtonUp(UINT nFlags, CPoint point)
2080 if(!OnButton(wmcmd::MUP, nFlags, point))
2081 __super::OnMButtonUp(nFlags, point);
2084 void CMainFrame::OnMButtonDblClk(UINT nFlags, CPoint point)
2086 SendMessage(WM_MBUTTONDOWN, nFlags, MAKELPARAM(point.x, point.y));
2087 if(!OnButton(wmcmd::MDBLCLK, nFlags, point))
2088 __super::OnMButtonDblClk(nFlags, point);
2091 void CMainFrame::OnRButtonDown(UINT nFlags, CPoint point)
2093 if(!OnButton(wmcmd::RDOWN, nFlags, point))
2094 __super::OnRButtonDown(nFlags, point);
2097 void CMainFrame::OnRButtonUp(UINT nFlags, CPoint point)
2099 if(!OnButton(wmcmd::RUP, nFlags, point))
2100 __super::OnRButtonUp(nFlags, point);
2103 void CMainFrame::OnRButtonDblClk(UINT nFlags, CPoint point)
2105 SendMessage(WM_RBUTTONDOWN, nFlags, MAKELPARAM(point.x, point.y));
2106 if(!OnButton(wmcmd::RDBLCLK, nFlags, point))
2107 __super::OnRButtonDblClk(nFlags, point);
2110 LRESULT CMainFrame::OnXButtonDown(WPARAM wParam, LPARAM lParam)
2112 SendMessage(WM_CANCELMODE);
2113 UINT fwButton = GET_XBUTTON_WPARAM(wParam);
2114 return OnButton(fwButton == XBUTTON1 ? wmcmd::X1DOWN : fwButton == XBUTTON2 ? wmcmd::X2DOWN : wmcmd::NONE,
2115 GET_KEYSTATE_WPARAM(wParam), CPoint(lParam));
2118 LRESULT CMainFrame::OnXButtonUp(WPARAM wParam, LPARAM lParam)
2120 UINT fwButton = GET_XBUTTON_WPARAM(wParam);
2121 return OnButton(fwButton == XBUTTON1 ? wmcmd::X1UP : fwButton == XBUTTON2 ? wmcmd::X2UP : wmcmd::NONE,
2122 GET_KEYSTATE_WPARAM(wParam), CPoint(lParam));
2125 LRESULT CMainFrame::OnXButtonDblClk(WPARAM wParam, LPARAM lParam)
2127 SendMessage(WM_XBUTTONDOWN, wParam, lParam);
2128 UINT fwButton = GET_XBUTTON_WPARAM(wParam);
2129 return OnButton(fwButton == XBUTTON1 ? wmcmd::X1DBLCLK : fwButton == XBUTTON2 ? wmcmd::X2DBLCLK : wmcmd::NONE,
2130 GET_KEYSTATE_WPARAM(wParam), CPoint(lParam));
2133 BOOL CMainFrame::OnMouseWheel(UINT nFlags, short zDelta, CPoint point)
2135 ScreenToClient(&point);
2137 BOOL fRet =
2138 zDelta > 0 ? OnButton(wmcmd::WUP, nFlags, point) :
2139 zDelta < 0 ? OnButton(wmcmd::WDOWN, nFlags, point) :
2140 FALSE;
2142 return fRet;
2145 void CMainFrame::OnMouseMove(UINT nFlags, CPoint point)
2147 if(m_iPlaybackMode == PM_DVD)
2149 CPoint vp = point - m_wndView.GetVideoRect().TopLeft();
2150 pDVDC->SelectAtPosition(vp);
2153 CSize diff = m_lastMouseMove - point;
2155 if(m_fFullScreen && (abs(diff.cx)+abs(diff.cy)) >= 1)
2157 int nTimeOut = AfxGetAppSettings().nShowBarsWhenFullScreenTimeOut;
2159 if(nTimeOut < 0)
2161 m_fHideCursor = false;
2162 if(AfxGetAppSettings().fShowBarsWhenFullScreen)
2163 ShowControls(AfxGetAppSettings().nCS);
2165 KillTimer(TIMER_FULLSCREENCONTROLBARHIDER);
2166 SetTimer(TIMER_FULLSCREENMOUSEHIDER, 2000, NULL);
2168 else if(nTimeOut == 0)
2170 CRect r;
2171 GetClientRect(r);
2172 r.top = r.bottom;
2174 POSITION pos = m_bars.GetHeadPosition();
2175 for(int i = 1; pos; i <<= 1)
2177 CControlBar* pNext = m_bars.GetNext(pos);
2178 CSize s = pNext->CalcFixedLayout(FALSE, TRUE);
2179 if(AfxGetAppSettings().nCS&i) r.top -= s.cy;
2182 // HACK: the controls would cover the menu too early hiding some buttons
2183 if(m_iPlaybackMode == PM_DVD
2184 && (m_iDVDDomain == DVD_DOMAIN_VideoManagerMenu
2185 || m_iDVDDomain == DVD_DOMAIN_VideoTitleSetMenu))
2186 r.top = r.bottom - 10;
2188 m_fHideCursor = false;
2190 if(r.PtInRect(point))
2192 if(AfxGetAppSettings().fShowBarsWhenFullScreen)
2193 ShowControls(AfxGetAppSettings().nCS);
2195 else
2197 if(AfxGetAppSettings().fShowBarsWhenFullScreen)
2198 ShowControls(CS_NONE, false);
2201 SetTimer(TIMER_FULLSCREENMOUSEHIDER, 2000, NULL);
2203 else
2205 m_fHideCursor = false;
2206 if(AfxGetAppSettings().fShowBarsWhenFullScreen)
2207 ShowControls(AfxGetAppSettings().nCS);
2209 SetTimer(TIMER_FULLSCREENCONTROLBARHIDER, nTimeOut*1000, NULL);
2210 SetTimer(TIMER_FULLSCREENMOUSEHIDER, max(nTimeOut*1000, 2000), NULL);
2214 m_lastMouseMove = point;
2216 __super::OnMouseMove(nFlags, point);
2219 LRESULT CMainFrame::OnNcHitTest(CPoint point)
2221 LRESULT nHitTest = __super::OnNcHitTest(point);
2222 return ((IsCaptionMenuHidden()) && nHitTest == HTCLIENT) ? HTCAPTION : nHitTest;
2225 void CMainFrame::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
2227 if(pScrollBar->IsKindOf(RUNTIME_CLASS(CVolumeCtrl)))
2229 OnPlayVolume(0);
2231 else if(pScrollBar->IsKindOf(RUNTIME_CLASS(CPlayerSeekBar)) && m_iMediaLoadState == MLS_LOADED)
2233 SeekTo(m_wndSeekBar.GetPos(), !!(::GetKeyState(VK_SHIFT)&0x8000));
2236 __super::OnHScroll(nSBCode, nPos, pScrollBar);
2239 void CMainFrame::OnInitMenu(CMenu* pMenu)
2241 __super::OnInitMenu(pMenu);
2243 MENUITEMINFO mii;
2244 mii.cbSize = sizeof(mii);
2246 for(UINT i = 0, j = pMenu->GetMenuItemCount(); i < j; i++)
2248 CString str;
2249 pMenu->GetMenuString(i, str, MF_BYPOSITION);
2251 CMenu* pSubMenu = NULL;
2253 if(str == ResStr(IDS_FAVORITES_POPUP))
2255 SetupFavoritesSubMenu();
2256 pSubMenu = &m_favorites;
2259 if(pSubMenu)
2261 mii.fMask = MIIM_STATE|MIIM_SUBMENU;
2262 mii.fType = MF_POPUP;
2263 mii.hSubMenu = pSubMenu->m_hMenu;
2264 mii.fState = (pSubMenu->GetMenuItemCount() > 0 ? MF_ENABLED : (MF_DISABLED|MF_GRAYED));
2265 pMenu->SetMenuItemInfo(i, &mii, TRUE);
2270 void CMainFrame::OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu)
2272 __super::OnInitMenuPopup(pPopupMenu, nIndex, bSysMenu);
2274 static CAtlStringMap<UINT> transl;
2276 if(transl.IsEmpty())
2278 transl[_T("Navigate")] = IDS_NAVIGATE_POPUP;
2279 transl[_T("Open Disc")] = IDS_OPENCDROM_POPUP;
2280 transl[_T("Filters")] = IDS_FILTERS_POPUP;
2281 transl[_T("Audio")] = IDS_AUDIO_POPUP;
2282 transl[_T("Subtitles")] = IDS_SUBTITLES_POPUP;
2283 transl[_T("Audio Language")] = IDS_AUDIOLANGUAGE_POPUP;
2284 transl[_T("Subtitle Language")] = IDS_SUBTITLELANGUAGE_POPUP;
2285 transl[_T("Video Angle")] = IDS_VIDEOANGLE_POPUP;
2286 transl[_T("Jump To...")] = IDS_JUMPTO_POPUP;
2287 transl[_T("Favorites")] = IDS_FAVORITES_POPUP;
2288 transl[_T("Shaders")] = IDS_SHADER_POPUP;
2289 transl[_T("Video Frame")] = IDS_VIDEOFRAME_POPUP;
2290 transl[_T("PanScan")] = IDS_PANSCAN_POPUP;
2291 transl[_T("Aspect Ratio")] = IDS_ASPECTRATIO_POPUP;
2292 transl[_T("Zoom")] = IDS_ZOOM_POPUP;
2295 MENUITEMINFO mii;
2296 mii.cbSize = sizeof(mii);
2298 for(UINT i = 0, j = pPopupMenu->GetMenuItemCount(); i < j; i++)
2300 CString str;
2301 pPopupMenu->GetMenuString(i, str, MF_BYPOSITION);
2303 CString lookupstr = str;
2304 lookupstr.Remove('&');
2306 CMenu* pSubMenu = NULL;
2308 UINT id;
2309 if(transl.Lookup(lookupstr, id))
2311 str = ResStr(id);
2312 // pPopupMenu->ModifyMenu(i, MF_BYPOSITION|MF_STRING, 0, str);
2313 MENUITEMINFO mii;
2314 mii.cbSize = sizeof(mii);
2315 mii.fMask = MIIM_STRING;
2316 mii.dwTypeData = (LPTSTR)(LPCTSTR)str;
2317 pPopupMenu->SetMenuItemInfo(i, &mii, TRUE);
2320 if(str == ResStr(IDS_NAVIGATE_POPUP))
2322 UINT fState = (m_iMediaLoadState == MLS_LOADED
2323 && (1/*m_iPlaybackMode == PM_DVD *//*|| (m_iPlaybackMode == PM_FILE && m_PlayList.GetCount() > 0)*/))
2324 ? MF_ENABLED
2325 : (MF_DISABLED|MF_GRAYED);
2327 pPopupMenu->EnableMenuItem(i, MF_BYPOSITION|fState);
2329 else if(str == ResStr(IDS_VIDEOFRAME_POPUP)
2330 || str == ResStr(IDS_PANSCAN_POPUP)
2331 || str == ResStr(IDS_ASPECTRATIO_POPUP)
2332 || str == ResStr(IDS_ZOOM_POPUP))
2334 UINT fState = (m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly)
2335 ? MF_ENABLED
2336 : (MF_DISABLED|MF_GRAYED);
2338 pPopupMenu->EnableMenuItem(i, MF_BYPOSITION|fState);
2340 else if(str == ResStr(IDS_OPENCDROM_POPUP))
2342 SetupOpenCDSubMenu();
2343 pSubMenu = &m_opencds;
2345 else if(str == ResStr(IDS_FILTERS_POPUP))
2347 SetupFiltersSubMenu();
2348 pSubMenu = &m_filters;
2350 else if(str == ResStr(IDS_AUDIO_POPUP))
2352 SetupAudioSwitcherSubMenu();
2353 pSubMenu = &m_audios;
2355 else if(str == ResStr(IDS_SUBTITLES_POPUP))
2357 SetupSubtitlesSubMenu();
2358 pSubMenu = &m_subtitles;
2360 else if(str == ResStr(IDS_AUDIOLANGUAGE_POPUP))
2362 SetupNavAudioSubMenu();
2363 pSubMenu = &m_navaudio;
2365 else if(str == ResStr(IDS_SUBTITLELANGUAGE_POPUP))
2367 SetupNavSubtitleSubMenu();
2368 pSubMenu = &m_navsubtitle;
2370 else if(str == ResStr(IDS_VIDEOANGLE_POPUP))
2372 SetupNavAngleSubMenu();
2373 pSubMenu = &m_navangle;
2375 else if(str == ResStr(IDS_JUMPTO_POPUP))
2377 SetupNavChaptersSubMenu();
2378 pSubMenu = &m_navchapters;
2380 else if(str == ResStr(IDS_FAVORITES_POPUP))
2382 SetupFavoritesSubMenu();
2383 pSubMenu = &m_favorites;
2385 else if(str == ResStr(IDS_SHADER_POPUP))
2387 SetupShadersSubMenu();
2388 pSubMenu = &m_shaders;
2391 if(pSubMenu)
2393 mii.fMask = MIIM_STATE|MIIM_SUBMENU;
2394 mii.fType = MF_POPUP;
2395 mii.hSubMenu = pSubMenu->m_hMenu;
2396 mii.fState = (pSubMenu->GetMenuItemCount() > 0 ? MF_ENABLED : (MF_DISABLED|MF_GRAYED));
2397 pPopupMenu->SetMenuItemInfo(i, &mii, TRUE);
2403 for(UINT i = 0, j = pPopupMenu->GetMenuItemCount(); i < j; i++)
2405 UINT nID = pPopupMenu->GetMenuItemID(i);
2406 if(nID == ID_SEPARATOR || nID == -1
2407 || nID >= ID_FAVORITES_FILE_START && nID <= ID_FAVORITES_FILE_END
2408 || nID >= ID_NAVIGATE_CHAP_SUBITEM_START && nID <= ID_NAVIGATE_CHAP_SUBITEM_END)
2409 continue;
2411 CString str;
2412 pPopupMenu->GetMenuString(i, str, MF_BYPOSITION);
2413 int k = str.Find('\t');
2414 if(k > 0) str = str.Left(k);
2416 CString key = CPPageAccelTbl::MakeAccelShortcutLabel(nID);
2417 if(!key.IsEmpty()) str += _T("\t") + key;
2419 if(key.IsEmpty() && i < 0) continue;
2421 // BUG(?): this disables menu item update ui calls for some reason...
2422 // pPopupMenu->ModifyMenu(i, MF_BYPOSITION|MF_STRING, nID, str);
2424 // this works fine
2425 MENUITEMINFO mii;
2426 mii.cbSize = sizeof(mii);
2427 mii.fMask = MIIM_STRING;
2428 mii.dwTypeData = (LPTSTR)(LPCTSTR)str;
2429 pPopupMenu->SetMenuItemInfo(i, &mii, TRUE);
2435 bool fPnSPresets = false;
2437 for(UINT i = 0, j = pPopupMenu->GetMenuItemCount(); i < j; i++)
2439 UINT nID = pPopupMenu->GetMenuItemID(i);
2441 if(nID >= ID_PANNSCAN_PRESETS_START && nID < ID_PANNSCAN_PRESETS_END)
2445 nID = pPopupMenu->GetMenuItemID(i);
2446 pPopupMenu->DeleteMenu(i, MF_BYPOSITION);
2447 j--;
2449 while(i < j && nID >= ID_PANNSCAN_PRESETS_START && nID < ID_PANNSCAN_PRESETS_END);
2451 nID = pPopupMenu->GetMenuItemID(i);
2454 if(nID == ID_VIEW_RESET)
2456 fPnSPresets = true;
2460 if(fPnSPresets)
2462 AppSettings& s = AfxGetAppSettings();
2463 int i = 0, j = s.m_pnspresets.GetCount();
2464 for(; i < j; i++)
2466 int k = 0;
2467 CString label = s.m_pnspresets[i].Tokenize(_T(","), k);
2468 pPopupMenu->InsertMenu(ID_VIEW_RESET, MF_BYCOMMAND, ID_PANNSCAN_PRESETS_START+i, label);
2470 // if(j > 0)
2472 pPopupMenu->InsertMenu(ID_VIEW_RESET, MF_BYCOMMAND, ID_PANNSCAN_PRESETS_START+i, ResStr(IDS_PANSCAN_EDIT));
2473 pPopupMenu->InsertMenu(ID_VIEW_RESET, MF_BYCOMMAND|MF_SEPARATOR);
2478 BOOL CMainFrame::OnMenu(CMenu* pMenu)
2480 if(!pMenu) return FALSE;
2482 KillTimer(TIMER_FULLSCREENMOUSEHIDER);
2483 m_fHideCursor = false;
2485 CPoint point;
2486 GetCursorPos(&point);
2488 pMenu->TrackPopupMenu(TPM_RIGHTBUTTON|TPM_NOANIMATION, point.x+1, point.y+1, this);
2490 return TRUE;
2493 void CMainFrame::OnMenuPlayerShort()
2495 if(IsCaptionMenuHidden())
2497 OnMenu(m_popupmain.GetSubMenu(0));
2499 else
2501 OnMenu(m_popup.GetSubMenu(0));
2505 void CMainFrame::OnMenuPlayerLong()
2507 OnMenu(m_popupmain.GetSubMenu(0));
2510 void CMainFrame::OnMenuFilters()
2512 SetupFiltersSubMenu();
2513 OnMenu(&m_filters);
2516 void CMainFrame::OnUpdatePlayerStatus(CCmdUI* pCmdUI)
2518 if(m_iMediaLoadState == MLS_LOADING)
2520 pCmdUI->SetText(ResStr(IDS_CONTROLS_OPENING));
2522 else if(m_iMediaLoadState == MLS_LOADED)
2524 CString msg;
2526 if(!m_playingmsg.IsEmpty())
2528 msg = m_playingmsg;
2530 else if(m_fCapturing)
2532 msg = ResStr(IDS_CONTROLS_CAPTURING);
2534 if(pAMDF)
2536 long lDropped = 0;
2537 pAMDF->GetNumDropped(&lDropped);
2538 long lNotDropped = 0;
2539 pAMDF->GetNumNotDropped(&lNotDropped);
2541 if((lDropped + lNotDropped) > 0)
2543 CString str;
2544 str.Format(_T(", Total: %d, Dropped: %d"), lDropped + lNotDropped, lDropped);
2545 msg += str;
2549 CComPtr<IPin> pPin;
2550 if(SUCCEEDED(pCGB->FindPin(m_wndCaptureBar.m_capdlg.m_pDst, PINDIR_INPUT, NULL, NULL, FALSE, 0, &pPin)))
2552 LONGLONG size = 0;
2553 if(CComQIPtr<IStream> pStream = pPin)
2555 pStream->Commit(STGC_DEFAULT);
2557 WIN32_FIND_DATA findFileData;
2558 HANDLE h = FindFirstFile(m_wndCaptureBar.m_capdlg.m_file, &findFileData);
2559 if(h != INVALID_HANDLE_VALUE)
2561 size = ((LONGLONG)findFileData.nFileSizeHigh << 32) | findFileData.nFileSizeLow;
2563 CString str;
2564 if(size < 1024i64*1024)
2565 str.Format(_T(", Size: %I64dKB"), size/1024);
2566 else //if(size < 1024i64*1024*1024)
2567 str.Format(_T(", Size: %I64dMB"), size/1024/1024);
2568 msg += str;
2570 FindClose(h);
2574 ULARGE_INTEGER FreeBytesAvailable, TotalNumberOfBytes, TotalNumberOfFreeBytes;
2575 if(GetDiskFreeSpaceEx(
2576 m_wndCaptureBar.m_capdlg.m_file.Left(m_wndCaptureBar.m_capdlg.m_file.ReverseFind('\\')+1),
2577 &FreeBytesAvailable, &TotalNumberOfBytes, &TotalNumberOfFreeBytes))
2579 CString str;
2580 if(FreeBytesAvailable.QuadPart < 1024i64*1024)
2581 str.Format(_T(", Free: %I64dKB"), FreeBytesAvailable.QuadPart/1024);
2582 else //if(FreeBytesAvailable.QuadPart < 1024i64*1024*1024)
2583 str.Format(_T(", Free: %I64dMB"), FreeBytesAvailable.QuadPart/1024/1024);
2584 msg += str;
2587 if(m_wndCaptureBar.m_capdlg.m_pMux)
2589 __int64 pos = 0;
2590 CComQIPtr<IMediaSeeking> pMuxMS = m_wndCaptureBar.m_capdlg.m_pMux;
2591 if(pMuxMS && SUCCEEDED(pMuxMS->GetCurrentPosition(&pos)) && pos > 0)
2593 double bytepersec = 10000000.0 * size / pos;
2594 if(bytepersec > 0)
2595 m_rtDurationOverride = __int64(10000000.0 * (FreeBytesAvailable.QuadPart+size) / bytepersec);
2599 if(m_wndCaptureBar.m_capdlg.m_pVidBuffer
2600 || m_wndCaptureBar.m_capdlg.m_pAudBuffer)
2602 int nFreeVidBuffers = 0, nFreeAudBuffers = 0;
2603 if(CComQIPtr<IBufferFilter> pVB = m_wndCaptureBar.m_capdlg.m_pVidBuffer)
2604 nFreeVidBuffers = pVB->GetFreeBuffers();
2605 if(CComQIPtr<IBufferFilter> pAB = m_wndCaptureBar.m_capdlg.m_pAudBuffer)
2606 nFreeAudBuffers = pAB->GetFreeBuffers();
2608 CString str;
2609 str.Format(_T(", Free V/A Buffers: %03d/%03d"), nFreeVidBuffers, nFreeAudBuffers);
2610 msg += str;
2614 else if(m_fBuffering)
2616 BeginEnumFilters(pGB, pEF, pBF)
2618 if(CComQIPtr<IAMNetworkStatus, &IID_IAMNetworkStatus> pAMNS = pBF)
2620 long BufferingProgress = 0;
2621 if(SUCCEEDED(pAMNS->get_BufferingProgress(&BufferingProgress)) && BufferingProgress > 0)
2623 msg.Format(ResStr(IDS_CONTROLS_BUFFERING), BufferingProgress);
2625 __int64 start = 0, stop = 0;
2626 m_wndSeekBar.GetRange(start, stop);
2627 m_fLiveWM = (stop == start);
2629 break;
2632 EndEnumFilters
2634 else if(pAMOP)
2636 __int64 t = 0, c = 0;
2637 if(SUCCEEDED(pAMOP->QueryProgress(&t, &c)) && t > 0 && c < t)
2638 msg.Format(ResStr(IDS_CONTROLS_BUFFERING), c*100/t);
2640 if(m_fUpdateInfoBar)
2641 OpenSetupInfoBar();
2644 OAFilterState fs = GetMediaState();
2645 pCmdUI->SetText(
2646 !msg.IsEmpty() ? msg :
2647 fs == State_Stopped ? ResStr(IDS_CONTROLS_STOPPED) :
2648 (fs == State_Paused || m_fFrameSteppingActive) ? ResStr(IDS_CONTROLS_PAUSED) :
2649 fs == State_Running ? ResStr(IDS_CONTROLS_PLAYING) :
2650 _T(""));
2652 else if(m_iMediaLoadState == MLS_CLOSING)
2654 pCmdUI->SetText(ResStr(IDS_CONTROLS_CLOSING));
2656 else
2658 pCmdUI->SetText(m_closingmsg);
2662 void CMainFrame::OnFilePostOpenmedia()
2664 OpenSetupInfoBar();
2666 OpenSetupStatsBar();
2668 OpenSetupStatusBar();
2670 // OpenSetupToolBar();
2672 OpenSetupCaptureBar();
2674 __int64 rtDur = 0;
2675 pMS->GetDuration(&rtDur);
2676 m_wndPlaylistBar.SetCurTime(rtDur);
2678 if(m_iPlaybackMode == PM_CAPTURE)
2680 ShowControlBar(&m_wndSubresyncBar, FALSE, TRUE);
2681 // ShowControlBar(&m_wndPlaylistBar, FALSE, TRUE);
2682 // ShowControlBar(&m_wndCaptureBar, TRUE, TRUE);
2685 if(m_pCAP) m_pCAP->SetSubtitleDelay(0);
2686 m_iMediaLoadState = MLS_LOADED;
2688 // IMPORTANT: must not call any windowing msgs before
2689 // this point, it will deadlock when OpenMediaPrivate is
2690 // still running and the renderer window was created on
2691 // the same worker-thread
2694 WINDOWPLACEMENT wp;
2695 wp.length = sizeof(wp);
2696 GetWindowPlacement(&wp);
2698 // restore magnification
2699 if(IsWindowVisible() && AfxGetAppSettings().fRememberZoomLevel
2700 && !(m_fFullScreen || wp.showCmd == SW_SHOWMAXIMIZED || wp.showCmd == SW_SHOWMINIMIZED))
2702 ZoomVideoWindow();
2706 if(!m_fAudioOnly && (AfxGetAppSettings().nCLSwitches&CLSW_FULLSCREEN))
2708 SendMessage(WM_COMMAND, ID_VIEW_FULLSCREEN);
2709 AfxGetAppSettings().nCLSwitches &= ~CLSW_FULLSCREEN;
2712 SendNowPlayingToMSN();
2713 SendNowPlayingTomIRC();
2716 void CMainFrame::OnUpdateFilePostOpenmedia(CCmdUI* pCmdUI)
2718 pCmdUI->Enable(m_iMediaLoadState == MLS_LOADING);
2721 void CMainFrame::OnFilePostClosemedia()
2723 m_wndView.SetVideoRect();
2724 m_wndSeekBar.Enable(false);
2725 m_wndSeekBar.SetPos(0);
2726 m_wndInfoBar.RemoveAllLines();
2727 m_wndStatsBar.RemoveAllLines();
2728 m_wndStatusBar.Clear();
2729 m_wndStatusBar.ShowTimer(false);
2731 if(IsWindow(m_wndSubresyncBar.m_hWnd))
2733 ShowControlBar(&m_wndSubresyncBar, FALSE, TRUE);
2734 SetSubtitle(NULL);
2737 if(IsWindow(m_wndCaptureBar.m_hWnd))
2739 ShowControlBar(&m_wndCaptureBar, FALSE, TRUE);
2740 m_wndCaptureBar.m_capdlg.SetupVideoControls(_T(""), NULL, NULL, NULL);
2741 m_wndCaptureBar.m_capdlg.SetupAudioControls(_T(""), NULL, CInterfaceArray<IAMAudioInputMixer>());
2744 RecalcLayout();
2746 SetWindowText(ResStr(IDR_MAINFRAME));
2748 SetAlwaysOnTop(AfxGetAppSettings().iOnTop);
2750 // this will prevent any further UI updates on the dynamically added menu items
2751 SetupFiltersSubMenu();
2752 SetupAudioSwitcherSubMenu();
2753 SetupSubtitlesSubMenu();
2754 SetupNavAudioSubMenu();
2755 SetupNavSubtitleSubMenu();
2756 SetupNavAngleSubMenu();
2757 SetupNavChaptersSubMenu();
2758 SetupFavoritesSubMenu();
2760 SendNowPlayingToMSN();
2763 void CMainFrame::OnUpdateFilePostClosemedia(CCmdUI* pCmdUI)
2765 pCmdUI->Enable(!!m_hWnd && m_iMediaLoadState == MLS_CLOSING);
2768 void CMainFrame::OnBossKey()
2770 SendMessage(WM_COMMAND, ID_PLAY_PAUSE);
2771 if(m_fFullScreen) SendMessage(WM_COMMAND, ID_VIEW_FULLSCREEN);
2772 SendMessage(WM_SYSCOMMAND, SC_MINIMIZE, -1);
2775 void CMainFrame::OnStreamAudio(UINT nID)
2777 nID -= ID_STREAM_AUDIO_NEXT;
2779 if(m_iMediaLoadState != MLS_LOADED) return;
2781 CComQIPtr<IAMStreamSelect> pSS = FindFilter(__uuidof(CAudioSwitcherFilter), pGB);
2782 if(!pSS) pSS = FindFilter(L"{D3CD7858-971A-4838-ACEC-40CA5D529DC8}", pGB); // morgan's switcher
2784 DWORD cStreams = 0;
2785 if(pSS && SUCCEEDED(pSS->Count(&cStreams)) && cStreams > 1)
2787 for(int i = 0; i < (int)cStreams; i++)
2789 AM_MEDIA_TYPE* pmt = NULL;
2790 DWORD dwFlags = 0;
2791 LCID lcid = 0;
2792 DWORD dwGroup = 0;
2793 WCHAR* pszName = NULL;
2794 if(FAILED(pSS->Info(i, &pmt, &dwFlags, &lcid, &dwGroup, &pszName, NULL, NULL)))
2795 return;
2796 if(pmt) DeleteMediaType(pmt);
2797 if(pszName) CoTaskMemFree(pszName);
2799 if(dwFlags&(AMSTREAMSELECTINFO_ENABLED|AMSTREAMSELECTINFO_EXCLUSIVE))
2801 pSS->Enable((i+(nID==0?1:cStreams-1))%cStreams, AMSTREAMSELECTENABLE_ENABLE);
2802 break;
2806 else if(m_iPlaybackMode == PM_FILE) SendMessage(WM_COMMAND, ID_OGM_AUDIO_NEXT+nID);
2807 else if(m_iPlaybackMode == PM_DVD) SendMessage(WM_COMMAND, ID_DVD_AUDIO_NEXT+nID);
2810 void CMainFrame::OnStreamSub(UINT nID)
2812 nID -= ID_STREAM_SUB_NEXT;
2814 if(m_iMediaLoadState != MLS_LOADED) return;
2816 int cnt = 0;
2817 POSITION pos = m_pSubStreams.GetHeadPosition();
2818 while(pos) cnt += m_pSubStreams.GetNext(pos)->GetStreamCount();
2820 if(cnt > 1)
2822 int i = ((m_iSubtitleSel&0x7fffffff)+(nID==0?1:cnt-1))%cnt;
2823 m_iSubtitleSel = i | (m_iSubtitleSel&0x80000000);
2824 UpdateSubtitle();
2825 SetFocus();
2827 else if(m_iPlaybackMode == PM_FILE) SendMessage(WM_COMMAND, ID_OGM_SUB_NEXT+nID);
2828 else if(m_iPlaybackMode == PM_DVD) SendMessage(WM_COMMAND, ID_DVD_SUB_NEXT+nID);
2831 void CMainFrame::OnStreamSubOnOff()
2833 if(m_iMediaLoadState != MLS_LOADED) return;
2835 int cnt = 0;
2836 POSITION pos = m_pSubStreams.GetHeadPosition();
2837 while(pos) cnt += m_pSubStreams.GetNext(pos)->GetStreamCount();
2839 if(cnt > 0)
2841 m_iSubtitleSel ^= 0x80000000;
2842 UpdateSubtitle();
2843 SetFocus();
2845 else if(m_iPlaybackMode == PM_DVD) SendMessage(WM_COMMAND, ID_DVD_SUB_ONOFF);
2848 void CMainFrame::OnOgmAudio(UINT nID)
2850 nID -= ID_OGM_AUDIO_NEXT;
2852 if(m_iMediaLoadState != MLS_LOADED) return;
2854 CComQIPtr<IAMStreamSelect> pSS = FindFilter(CLSID_OggSplitter, pGB);
2855 if(!pSS) pSS = FindFilter(L"{55DA30FC-F16B-49fc-BAA5-AE59FC65F82D}", pGB);
2856 if(!pSS) return;
2858 CAtlArray<int> snds;
2859 int iSel = -1;
2861 DWORD cStreams = 0;
2862 if(SUCCEEDED(pSS->Count(&cStreams)) && cStreams > 1)
2864 for(int i = 0; i < (int)cStreams; i++)
2866 AM_MEDIA_TYPE* pmt = NULL;
2867 DWORD dwFlags = 0;
2868 LCID lcid = 0;
2869 DWORD dwGroup = 0;
2870 WCHAR* pszName = NULL;
2871 if(FAILED(pSS->Info(i, &pmt, &dwFlags, &lcid, &dwGroup, &pszName, NULL, NULL)))
2872 return;
2874 if(dwGroup == 1)
2876 if(dwFlags&(AMSTREAMSELECTINFO_ENABLED|AMSTREAMSELECTINFO_EXCLUSIVE))
2877 iSel = snds.GetCount();
2878 snds.Add(i);
2881 if(pmt) DeleteMediaType(pmt);
2882 if(pszName) CoTaskMemFree(pszName);
2886 int cnt = snds.GetCount();
2887 if(cnt > 1 && iSel >= 0)
2888 pSS->Enable(snds[(iSel+(nID==0?1:cnt-1))%cnt], AMSTREAMSELECTENABLE_ENABLE);
2892 void CMainFrame::OnOgmSub(UINT nID)
2894 nID -= ID_OGM_SUB_NEXT;
2896 if(m_iMediaLoadState != MLS_LOADED) return;
2898 CComQIPtr<IAMStreamSelect> pSS = FindFilter(CLSID_OggSplitter, pGB);
2899 if(!pSS) pSS = FindFilter(L"{55DA30FC-F16B-49fc-BAA5-AE59FC65F82D}", pGB);
2900 if(!pSS) return;
2902 CAtlArray<int> subs;
2903 int iSel = -1;
2905 DWORD cStreams = 0;
2906 if(SUCCEEDED(pSS->Count(&cStreams)) && cStreams > 1)
2908 for(int i = 0; i < (int)cStreams; i++)
2910 AM_MEDIA_TYPE* pmt = NULL;
2911 DWORD dwFlags = 0;
2912 LCID lcid = 0;
2913 DWORD dwGroup = 0;
2914 WCHAR* pszName = NULL;
2915 if(FAILED(pSS->Info(i, &pmt, &dwFlags, &lcid, &dwGroup, &pszName, NULL, NULL)))
2916 return;
2918 if(dwGroup == 2)
2920 if(dwFlags&(AMSTREAMSELECTINFO_ENABLED|AMSTREAMSELECTINFO_EXCLUSIVE))
2921 iSel = subs.GetCount();
2922 subs.Add(i);
2925 if(pmt) DeleteMediaType(pmt);
2926 if(pszName) CoTaskMemFree(pszName);
2930 int cnt = subs.GetCount();
2931 if(cnt > 1 && iSel >= 0)
2932 pSS->Enable(subs[(iSel+(nID==0?1:cnt-1))%cnt], AMSTREAMSELECTENABLE_ENABLE);
2936 void CMainFrame::OnDvdAngle(UINT nID)
2938 nID -= ID_DVD_ANGLE_NEXT;
2940 if(m_iMediaLoadState != MLS_LOADED) return;
2942 if(pDVDI && pDVDC)
2944 ULONG ulAnglesAvailable, ulCurrentAngle;
2945 if(SUCCEEDED(pDVDI->GetCurrentAngle(&ulAnglesAvailable, &ulCurrentAngle)) && ulAnglesAvailable > 1)
2947 ulCurrentAngle += nID==0 ? 1 : ulAnglesAvailable-1;
2948 if(ulCurrentAngle > ulAnglesAvailable) ulCurrentAngle = 1;
2949 else if(ulCurrentAngle < 1) ulCurrentAngle = ulAnglesAvailable;
2950 pDVDC->SelectAngle(ulCurrentAngle, DVD_CMD_FLAG_Block, NULL);
2955 void CMainFrame::OnDvdAudio(UINT nID)
2957 nID -= ID_DVD_AUDIO_NEXT;
2959 if(m_iMediaLoadState != MLS_LOADED) return;
2961 if(pDVDI && pDVDC)
2963 ULONG nStreamsAvailable, nCurrentStream;
2964 if(SUCCEEDED(pDVDI->GetCurrentAudio(&nStreamsAvailable, &nCurrentStream)) && nStreamsAvailable > 1)
2965 pDVDC->SelectAudioStream((nCurrentStream+(nID==0?1:nStreamsAvailable-1))%nStreamsAvailable, DVD_CMD_FLAG_Block, NULL);
2969 void CMainFrame::OnDvdSub(UINT nID)
2971 nID -= ID_DVD_SUB_NEXT;
2973 if(m_iMediaLoadState != MLS_LOADED) return;
2975 if(pDVDI && pDVDC)
2977 ULONG ulStreamsAvailable, ulCurrentStream;
2978 BOOL bIsDisabled;
2979 if(SUCCEEDED(pDVDI->GetCurrentSubpicture(&ulStreamsAvailable, &ulCurrentStream, &bIsDisabled))
2980 && ulStreamsAvailable > 1)
2982 pDVDC->SelectSubpictureStream(
2983 (ulCurrentStream+(nID==0?1:ulStreamsAvailable-1))%ulStreamsAvailable,
2984 DVD_CMD_FLAG_Block, NULL);
2989 void CMainFrame::OnDvdSubOnOff()
2991 if(m_iMediaLoadState != MLS_LOADED) return;
2993 if(pDVDI && pDVDC)
2995 ULONG ulStreamsAvailable, ulCurrentStream;
2996 BOOL bIsDisabled;
2997 if(SUCCEEDED(pDVDI->GetCurrentSubpicture(&ulStreamsAvailable, &ulCurrentStream, &bIsDisabled)))
2999 pDVDC->SetSubpictureState(bIsDisabled, DVD_CMD_FLAG_Block, NULL);
3005 // menu item handlers
3008 // file
3010 void CMainFrame::OnFileOpenQuick()
3012 if(m_iMediaLoadState == MLS_LOADING || !IsWindow(m_wndPlaylistBar)) return;
3014 CString filter;
3015 CAtlArray<CString> mask;
3016 AfxGetAppSettings().Formats.GetFilter(filter, mask);
3018 COpenFileDlg fd(mask, true, NULL, NULL,
3019 OFN_EXPLORER|OFN_ENABLESIZING|OFN_HIDEREADONLY|OFN_ALLOWMULTISELECT|OFN_ENABLEINCLUDENOTIFY,
3020 filter, this);
3021 if(fd.DoModal() != IDOK) return;
3023 CAtlList<CString> fns;
3025 POSITION pos = fd.GetStartPosition();
3026 while(pos) fns.AddTail(fd.GetNextPathName(pos));
3028 bool fMultipleFiles = false;
3030 if(fns.GetCount() > 1
3031 || fns.GetCount() == 1
3032 && (fns.GetHead()[fns.GetHead().GetLength()-1] == '\\'
3033 || fns.GetHead()[fns.GetHead().GetLength()-1] == '*'))
3035 fMultipleFiles = true;
3038 SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
3040 ShowWindow(SW_SHOW);
3041 SetForegroundWindow();
3043 m_wndPlaylistBar.Open(fns, fMultipleFiles);
3045 if(m_wndPlaylistBar.GetCount() == 1 && m_wndPlaylistBar.IsWindowVisible() && !m_wndPlaylistBar.IsFloating())
3047 ShowControlBar(&m_wndPlaylistBar, FALSE, TRUE);
3050 OpenCurPlaylistItem();
3053 void CMainFrame::OnFileOpenmedia()
3055 if(m_iMediaLoadState == MLS_LOADING || !IsWindow(m_wndPlaylistBar)) return;
3057 COpenDlg dlg;
3058 if(dlg.DoModal() != IDOK || dlg.m_fns.GetCount() == 0) return;
3060 if(dlg.m_fAppendPlaylist)
3062 m_wndPlaylistBar.Append(dlg.m_fns, dlg.m_fMultipleFiles);
3063 return;
3066 SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
3068 ShowWindow(SW_SHOW);
3069 SetForegroundWindow();
3071 m_wndPlaylistBar.Open(dlg.m_fns, dlg.m_fMultipleFiles);
3073 if(m_wndPlaylistBar.GetCount() == 1 && m_wndPlaylistBar.IsWindowVisible() && !m_wndPlaylistBar.IsFloating())
3075 ShowControlBar(&m_wndPlaylistBar, FALSE, TRUE);
3078 OpenCurPlaylistItem();
3081 void CMainFrame::OnUpdateFileOpen(CCmdUI* pCmdUI)
3083 pCmdUI->Enable(m_iMediaLoadState != MLS_LOADING);
3086 BOOL CMainFrame::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCDS)
3088 if(m_iMediaLoadState == MLS_LOADING || !IsWindow(m_wndPlaylistBar))
3089 return FALSE;
3091 if(pCDS->dwData != 0x6ABE51 || pCDS->cbData < sizeof(DWORD))
3092 return FALSE;
3094 DWORD len = *((DWORD*)pCDS->lpData);
3095 TCHAR* pBuff = (TCHAR*)((DWORD*)pCDS->lpData + 1);
3096 TCHAR* pBuffEnd = (TCHAR*)((BYTE*)pBuff + pCDS->cbData - sizeof(DWORD));
3098 CAtlList<CString> cmdln;
3100 while(len-- > 0)
3102 CString str;
3103 while(pBuff < pBuffEnd && *pBuff) str += *pBuff++;
3104 pBuff++;
3105 cmdln.AddTail(str);
3108 AppSettings& s = AfxGetAppSettings();
3110 s.ParseCommandLine(cmdln);
3112 POSITION pos = s.slFilters.GetHeadPosition();
3113 while(pos)
3115 CString fullpath = MakeFullPath(s.slFilters.GetNext(pos));
3117 CPath tmp(fullpath);
3118 tmp.RemoveFileSpec();
3119 tmp.AddBackslash();
3120 CString path = tmp;
3122 WIN32_FIND_DATA fd = {0};
3123 HANDLE hFind = FindFirstFile(fullpath, &fd);
3124 if(hFind != INVALID_HANDLE_VALUE)
3128 if(fd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) continue;
3130 CFilterMapper2 fm2(false);
3131 fm2.Register(path + fd.cFileName);
3132 while(!fm2.m_filters.IsEmpty())
3134 if(FilterOverride* f = fm2.m_filters.RemoveTail())
3136 f->fTemporary = true;
3138 bool fFound = false;
3140 POSITION pos2 = s.filters.GetHeadPosition();
3141 while(pos2)
3143 FilterOverride* f2 = s.filters.GetNext(pos2);
3144 if(f2->type == FilterOverride::EXTERNAL && !f2->path.CompareNoCase(f->path))
3146 fFound = true;
3147 break;
3151 if(!fFound)
3153 CAutoPtr<FilterOverride> p(f);
3154 s.filters.AddHead(p);
3159 while(FindNextFile(hFind, &fd));
3161 FindClose(hFind);
3165 bool fSetForegroundWindow = false;
3167 if((s.nCLSwitches&CLSW_DVD) && !s.slFiles.IsEmpty())
3169 SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
3170 fSetForegroundWindow = true;
3172 CAutoPtr<OpenDVDData> p(new OpenDVDData());
3173 if(p) {p->path = s.slFiles.GetHead(); p->subs.AddTailList(&s.slSubs);}
3174 OpenMedia(p);
3176 else if(s.nCLSwitches&CLSW_CD)
3178 SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
3179 fSetForegroundWindow = true;
3181 CAtlList<CString> sl;
3183 if(!s.slFiles.IsEmpty())
3185 GetCDROMType(s.slFiles.GetHead()[0], sl);
3187 else
3189 CString dir;
3190 dir.ReleaseBufferSetLength(GetCurrentDirectory(MAX_PATH, dir.GetBuffer(MAX_PATH)));
3192 GetCDROMType(dir[0], sl);
3194 for(TCHAR drive = 'C'; sl.IsEmpty() && drive <= 'Z'; drive++)
3196 GetCDROMType(drive, sl);
3200 m_wndPlaylistBar.Open(sl, true);
3201 OpenCurPlaylistItem();
3203 else if(!s.slFiles.IsEmpty())
3205 bool fMulti = s.slFiles.GetCount() > 1;
3207 CAtlList<CString> sl;
3208 sl.AddTailList(&s.slFiles);
3209 if(!fMulti) sl.AddTailList(&s.slDubs);
3211 if((s.nCLSwitches&CLSW_ADD) && m_wndPlaylistBar.GetCount() > 0)
3213 m_wndPlaylistBar.Append(sl, fMulti, &s.slSubs);
3215 if(s.nCLSwitches&(CLSW_OPEN|CLSW_PLAY))
3217 m_wndPlaylistBar.SetLast();
3218 OpenCurPlaylistItem();
3221 else
3223 SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
3224 fSetForegroundWindow = true;
3226 m_wndPlaylistBar.Open(sl, fMulti, &s.slSubs);
3227 OpenCurPlaylistItem((s.nCLSwitches&CLSW_STARTVALID) ? s.rtStart : 0);
3229 s.nCLSwitches &= ~CLSW_STARTVALID;
3230 s.rtStart = 0;
3233 else
3235 s.nCLSwitches = CLSW_NONE;
3238 if(fSetForegroundWindow && !(s.nCLSwitches&CLSW_NOFOCUS))
3239 SetForegroundWindow();
3241 s.nCLSwitches &= ~CLSW_NOFOCUS;
3243 return TRUE;
3246 void CMainFrame::OnFileOpendvd()
3248 if(m_iMediaLoadState == MLS_LOADING) return;
3250 SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
3251 SetForegroundWindow();
3253 ShowWindow(SW_SHOW);
3255 CAutoPtr<OpenDVDData> p(new OpenDVDData());
3256 if(p)
3258 AppSettings& s = AfxGetAppSettings();
3259 if(s.fUseDVDPath && !s.sDVDPath.IsEmpty())
3261 p->path = s.sDVDPath;
3262 p->path.Replace('/', '\\');
3263 if(p->path[p->path.GetLength()-1] != '\\') p->path += '\\';
3266 OpenMedia(p);
3269 void CMainFrame::OnFileOpendevice()
3271 if(m_iMediaLoadState == MLS_LOADING) return;
3273 COpenCapDeviceDlg capdlg;
3274 if(capdlg.DoModal() != IDOK)
3275 return;
3277 SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
3278 SetForegroundWindow();
3280 ShowWindow(SW_SHOW);
3282 m_wndPlaylistBar.Empty();
3284 CAutoPtr<OpenDeviceData> p(new OpenDeviceData());
3285 if(p) {p->DisplayName[0] = capdlg.m_vidstr; p->DisplayName[1] = capdlg.m_audstr;}
3286 OpenMedia(p);
3289 void CMainFrame::OnFileOpenCD(UINT nID)
3291 nID -= ID_FILE_OPEN_CD_START;
3293 nID++;
3294 for(TCHAR drive = 'C'; drive <= 'Z'; drive++)
3296 CAtlList<CString> sl;
3298 switch(GetCDROMType(drive, sl))
3300 case CDROM_Audio:
3301 case CDROM_VideoCD:
3302 case CDROM_DVDVideo:
3303 nID--;
3304 break;
3305 default:
3306 break;
3309 if(nID == 0)
3311 SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
3312 SetForegroundWindow();
3314 ShowWindow(SW_SHOW);
3316 m_wndPlaylistBar.Open(sl, true);
3317 OpenCurPlaylistItem();
3319 break;
3324 void CMainFrame::OnDropFiles(HDROP hDropInfo)
3326 SetForegroundWindow();
3328 if(m_wndPlaylistBar.IsWindowVisible())
3330 m_wndPlaylistBar.OnDropFiles(hDropInfo);
3331 return;
3334 CAtlList<CString> sl;
3336 UINT nFiles = ::DragQueryFile(hDropInfo, (UINT)-1, NULL, 0);
3338 for(UINT iFile = 0; iFile < nFiles; iFile++)
3340 CString fn;
3341 fn.ReleaseBuffer(::DragQueryFile(hDropInfo, iFile, fn.GetBuffer(MAX_PATH), MAX_PATH));
3342 sl.AddTail(fn);
3345 ::DragFinish(hDropInfo);
3347 if(sl.IsEmpty()) return;
3349 if(sl.GetCount() == 1 && m_iMediaLoadState == MLS_LOADED && m_pCAP)
3351 if(LoadSubtitle(sl.GetHead()))
3353 SetSubtitle(m_pSubStreams.GetTail());
3354 CPath p(sl.GetHead());
3355 p.StripPath();
3356 SendStatusMessage(CString((LPCTSTR)p) + _T(" loaded successfully"), 3000);
3357 return;
3361 m_wndPlaylistBar.Open(sl, true);
3362 OpenCurPlaylistItem();
3365 void CMainFrame::OnFileSaveAs()
3367 CString ext, in = m_wndPlaylistBar.GetCur(), out = in;
3369 if(out.Find(_T("://")) < 0)
3371 ext = CString(CPath(out).GetExtension()).MakeLower();
3372 if(ext == _T(".cda")) out = out.Left(out.GetLength()-4) + _T(".wav");
3373 else if(ext == _T(".ifo")) out = out.Left(out.GetLength()-4) + _T(".vob");
3375 else
3377 out.Empty();
3380 CFileDialog fd(FALSE, 0, out,
3381 OFN_EXPLORER|OFN_ENABLESIZING|OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_PATHMUSTEXIST,
3382 _T("All files (*.*)|*.*||"), this, 0);
3383 if(fd.DoModal() != IDOK || !in.CompareNoCase(fd.GetPathName())) return;
3385 CPath p(fd.GetPathName());
3386 if(!ext.IsEmpty()) p.AddExtension(ext);
3388 OAFilterState fs = State_Stopped;
3389 pMC->GetState(0, &fs);
3390 if(fs == State_Running) pMC->Pause();
3392 CSaveDlg dlg(in, p);
3393 dlg.DoModal();
3395 if(fs == State_Running) pMC->Run();
3398 void CMainFrame::OnUpdateFileSaveAs(CCmdUI* pCmdUI)
3400 if(m_iMediaLoadState != MLS_LOADED || m_iPlaybackMode != PM_FILE)
3402 pCmdUI->Enable(FALSE);
3403 return;
3406 CString fn = m_wndPlaylistBar.GetCur();
3407 CString ext = fn.Mid(fn.ReverseFind('.')+1).MakeLower();
3409 int i = fn.Find(_T("://"));
3410 if(i >= 0)
3412 CString protocol = fn.Left(i).MakeLower();
3413 if(protocol != _T("http"))
3415 pCmdUI->Enable(FALSE);
3416 return;
3420 if((GetVersion()&0x80000000) && (ext == _T("cda") || ext == _T("ifo")))
3422 pCmdUI->Enable(FALSE);
3423 return;
3426 pCmdUI->Enable(TRUE);
3429 bool CMainFrame::GetDIB(BYTE** ppData, long& size, bool fSilent)
3431 if(!ppData) return false;
3433 *ppData = NULL;
3434 size = 0;
3436 bool fNeedsToPause = !m_pCAP;
3437 if(fNeedsToPause) fNeedsToPause = !IsVMR7InGraph(pGB);
3438 if(fNeedsToPause) fNeedsToPause = !IsVMR9InGraph(pGB);
3440 OAFilterState fs = GetMediaState();
3442 if(!(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly && (fs == State_Paused || fs == State_Running)))
3443 return false;
3445 if(fs == State_Running && fNeedsToPause)
3447 pMC->Pause();
3448 GetMediaState(); // wait for completion of the pause command
3451 HRESULT hr = S_OK;
3452 CString errmsg;
3456 if(m_pCAP)
3458 hr = m_pCAP->GetDIB(NULL, (DWORD*)&size);
3459 if(FAILED(hr))
3461 OnPlayPause();GetMediaState(); // Pause and retry to support ffdshow queueing.
3462 int retry = 0;
3463 while(FAILED(hr) && retry < 20)
3465 hr = m_pCAP->GetDIB(*ppData, (DWORD*)&size);
3466 if(SUCCEEDED(hr)) break;
3467 Sleep(1);
3468 retry++;
3470 if(FAILED(hr))
3471 {errmsg.Format(_T("GetDIB failed, hr = %08x"), hr); break;}
3474 if(!(*ppData = new BYTE[size])) return false;
3476 hr = m_pCAP->GetDIB(*ppData, (DWORD*)&size);
3477 if(FAILED(hr)) {errmsg.Format(_T("GetDIB failed, hr = %08x"), hr); break;}
3479 else
3481 hr = pBV->GetCurrentImage(&size, NULL);
3482 if(FAILED(hr) || size == 0) {errmsg.Format(_T("GetCurrentImage failed, hr = %08x"), hr); break;}
3484 if(!(*ppData = new BYTE[size])) return false;
3486 hr = pBV->GetCurrentImage(&size, (long*)*ppData);
3487 if(FAILED(hr)) {errmsg.Format(_T("GetCurrentImage failed, hr = %08x"), hr); break;}
3490 while(0);
3492 if(!fSilent)
3494 if(!errmsg.IsEmpty())
3496 AfxMessageBox(errmsg, MB_OK);
3500 if(fs == State_Running && GetMediaState() != State_Running)
3502 pMC->Run();
3505 if(FAILED(hr))
3507 if(*ppData) {ASSERT(0); delete [] *ppData; *ppData = NULL;} // huh?
3508 return false;
3511 return true;
3514 #include "jpeg.h"
3515 #include "pngdib.h"
3517 void CMainFrame::SaveDIB(LPCTSTR fn, BYTE* pData, long size)
3519 CString ext = CString(CPath(fn).GetExtension()).MakeLower();
3521 if(ext == _T(".bmp"))
3523 if(FILE* f = _tfopen(fn, _T("wb")))
3525 BITMAPINFO* bi = (BITMAPINFO*)pData;
3527 BITMAPFILEHEADER bfh;
3528 bfh.bfType = 'MB';
3529 bfh.bfOffBits = sizeof(bfh) + sizeof(bi->bmiHeader);
3530 bfh.bfSize = sizeof(bfh) + size;
3531 bfh.bfReserved1 = bfh.bfReserved2 = 0;
3533 if(bi->bmiHeader.biBitCount <= 8)
3535 if(bi->bmiHeader.biClrUsed) bfh.bfOffBits += bi->bmiHeader.biClrUsed * sizeof(bi->bmiColors[0]);
3536 else bfh.bfOffBits += (1 << bi->bmiHeader.biBitCount) * sizeof(bi->bmiColors[0]);
3539 fwrite(&bfh, 1, sizeof(bfh), f);
3540 fwrite(pData, 1, size, f);
3542 fclose(f);
3544 else
3546 AfxMessageBox(_T("Cannot create file"), MB_OK);
3549 else if(ext == _T(".png"))
3551 DWORD bmpsize = size;
3552 LPBITMAPINFOHEADER pdib;
3553 LPBITMAPFILEHEADER pbmfh;
3554 void *pbits;
3555 PNGDIB *pngdib;
3556 int ret;
3558 BITMAPINFO* bi = (BITMAPINFO*)pData;
3560 BITMAPFILEHEADER bfh;
3561 bfh.bfType = 'MB';
3562 bfh.bfOffBits = sizeof(bfh) + sizeof(bi->bmiHeader);
3563 bfh.bfSize = sizeof(bfh) + size;
3564 bfh.bfReserved1 = bfh.bfReserved2 = 0;
3566 if(bi->bmiHeader.biBitCount <= 8)
3568 if(bi->bmiHeader.biClrUsed) bfh.bfOffBits += bi->bmiHeader.biClrUsed * sizeof(bi->bmiColors[0]);
3569 else bfh.bfOffBits += (1 << bi->bmiHeader.biBitCount) * sizeof(bi->bmiColors[0]);
3571 pbmfh = (LPBITMAPFILEHEADER)&bfh;
3572 pbits = &pData[pbmfh->bfOffBits-sizeof(bfh)];
3573 pdib = (LPBITMAPINFOHEADER)pData;
3574 pngdib = pngdib_d2p_init();
3575 pngdib_d2p_set_dib(pngdib,pdib,bmpsize,pbits,0);
3576 pngdib_d2p_set_png_filename(pngdib, fn);
3577 pngdib_d2p_set_gamma_label(pngdib, 1, PNGDIB_DEFAULT_FILE_GAMMA);
3578 ret = pngdib_d2p_run(pngdib);
3579 pngdib_done(pngdib);
3580 if(ret) {
3581 CString err_str;
3582 err_str.Format(_T("%s\n%s (%d)"), "Cannot create file", pngdib_get_error_msg(pngdib), ret);
3583 AfxMessageBox(err_str, MB_OK);
3586 else if(ext == _T(".jpg"))
3588 CJpegEncoderFile(fn).Encode(pData);
3591 CPath p(fn);
3593 if(CDC* pDC = m_wndStatusBar.m_status.GetDC())
3595 CRect r;
3596 m_wndStatusBar.m_status.GetClientRect(r);
3597 p.CompactPath(pDC->m_hDC, r.Width());
3598 m_wndStatusBar.m_status.ReleaseDC(pDC);
3601 SendStatusMessage((LPCTSTR)p, 3000);
3604 void CMainFrame::SaveImage(LPCTSTR fn)
3606 BYTE* pData = NULL;
3607 long size = 0;
3609 if(GetDIB(&pData, size))
3611 SaveDIB(fn, pData, size);
3612 delete [] pData;
3616 void CMainFrame::SaveThumbnails(LPCTSTR fn)
3618 if(!pMC || !pMS || m_iPlaybackMode != PM_FILE /*&& m_iPlaybackMode != PM_DVD*/)
3619 return;
3621 REFERENCE_TIME rtPos = GetPos();
3622 REFERENCE_TIME rtDur = GetDur();
3624 if(rtDur <= 0)
3626 AfxMessageBox(_T("Cannot create thumbnails for files with no duration"));
3627 return;
3630 pMC->Pause();
3631 GetMediaState(); // wait for completion of the pause command
3635 CSize video, wh(0, 0), arxy(0, 0);
3637 if(m_pCAP)
3639 wh = m_pCAP->GetVideoSize(false);
3640 arxy = m_pCAP->GetVideoSize(true);
3642 else
3644 pBV->GetVideoSize(&wh.cx, &wh.cy);
3646 long arx = 0, ary = 0;
3647 CComQIPtr<IBasicVideo2> pBV2 = pBV;
3648 if(pBV2 && SUCCEEDED(pBV2->GetPreferredAspectRatio(&arx, &ary)) && arx > 0 && ary > 0)
3649 arxy.SetSize(arx, ary);
3652 if(wh.cx <= 0 || wh.cy <= 0)
3654 AfxMessageBox(_T("Failed to get video frame size"));
3655 return;
3658 // with the overlay mixer IBasicVideo2 won't tell the new AR when changed dynamically
3659 DVD_VideoAttributes VATR;
3660 if(m_iPlaybackMode == PM_DVD && SUCCEEDED(pDVDI->GetCurrentVideoAttributes(&VATR)))
3661 arxy.SetSize(VATR.ulAspectX, VATR.ulAspectY);
3663 video = (arxy.cx <= 0 || arxy.cy <= 0) ? wh : CSize(MulDiv(wh.cy, arxy.cx, arxy.cy), wh.cy);
3667 AppSettings& s = AfxGetAppSettings();
3669 int cols = max(1, min(8, s.ThumbCols));
3670 int rows = max(1, min(8, s.ThumbRows));
3672 int margin = 5;
3673 int infoheight = 70;
3674 int width = max(256, min(2048, s.ThumbWidth));
3675 int height = width * video.cy / video.cx * rows / cols + infoheight;
3677 int dibsize = sizeof(BITMAPINFOHEADER) + width*height*4;
3679 CAutoVectorPtr<BYTE> dib;
3680 if(!dib.Allocate(dibsize))
3682 AfxMessageBox(_T("Out of memory, go buy some more!"));
3683 return;
3686 BITMAPINFOHEADER* bih = (BITMAPINFOHEADER*)(BYTE*)dib;
3687 memset(bih, 0, sizeof(BITMAPINFOHEADER));
3688 bih->biSize = sizeof(BITMAPINFOHEADER);
3689 bih->biWidth = width;
3690 bih->biHeight = height;
3691 bih->biPlanes = 1;
3692 bih->biBitCount = 32;
3693 bih->biCompression = BI_RGB;
3694 bih->biSizeImage = width*height*4;
3695 memsetd(bih + 1, 0xffffff, bih->biSizeImage);
3697 SubPicDesc spd;
3698 spd.w = width;
3699 spd.h = height;
3700 spd.bpp = 32;
3701 spd.pitch = -width*4;
3702 spd.bits = (BYTE*)(bih + 1) + (width*4)*(height-1);
3705 BYTE* p = (BYTE*)spd.bits;
3706 for(int y = 0; y < spd.h; y++, p += spd.pitch)
3707 for(int x = 0; x < spd.w; x++)
3708 ((DWORD*)p)[x] = 0x010101 * (0xe0 + 0x08*y/spd.h + 0x18*(spd.w-x)/spd.w);
3711 CCritSec csSubLock;
3712 RECT bbox;
3714 for(int i = 1, pics = cols*rows; i <= pics; i++)
3716 REFERENCE_TIME rt = rtDur * i / (pics+1);
3717 DVD_HMSF_TIMECODE hmsf = RT2HMSF(rt, 25);
3719 SeekTo(rt);
3721 m_VolumeBeforeFrameStepping = m_wndToolBar.Volume;
3722 pBA->put_Volume(-10000);
3724 HRESULT hr = pFS ? pFS->Step(1, NULL) : E_FAIL;
3726 if(FAILED(hr))
3728 pBA->put_Volume(m_VolumeBeforeFrameStepping);
3729 AfxMessageBox(_T("Cannot frame step, try a different video renderer."));
3730 return;
3733 HANDLE hGraphEvent = NULL;
3734 pME->GetEventHandle((OAEVENT*)&hGraphEvent);
3736 while(hGraphEvent && WaitForSingleObject(hGraphEvent, INFINITE) == WAIT_OBJECT_0)
3738 LONG evCode = 0, evParam1, evParam2;
3739 while(SUCCEEDED(pME->GetEvent(&evCode, (LONG_PTR*)&evParam1, (LONG_PTR*)&evParam2, 0)))
3741 pME->FreeEventParams(evCode, evParam1, evParam2);
3742 if(EC_STEP_COMPLETE == evCode) hGraphEvent = NULL;
3746 pBA->put_Volume(m_VolumeBeforeFrameStepping);
3748 int col = (i-1)%cols;
3749 int row = (i-1)/cols;
3751 CSize s((width-margin*2)/cols, (height-margin*2-infoheight)/rows);
3752 CPoint p(margin+col*s.cx, margin+row*s.cy+infoheight);
3753 CRect r(p, s);
3754 r.DeflateRect(margin, margin);
3756 CRenderedTextSubtitle rts(&csSubLock);
3757 rts.CreateDefaultStyle(0);
3758 rts.m_dstScreenSize.SetSize(width, height);
3759 STSStyle* style = new STSStyle();
3760 style->marginRect.SetRectEmpty();
3761 rts.AddStyle(_T("thumbs"), style);
3763 CStringW str;
3764 str.Format(L"{\\an7\\1c&Hffffff&\\4a&Hb0&\\bord1\\shad4\\be1}{\\p1}m %d %d l %d %d %d %d %d %d{\\p}",
3765 r.left, r.top, r.right, r.top, r.right, r.bottom, r.left, r.bottom);
3766 rts.Add(str, true, 0, 1, _T("thumbs"));
3767 str.Format(L"{\\an3\\1c&Hffffff&\\3c&H000000&\\alpha&H80&\\fs16\\b1\\bord2\\shad0\\pos(%d,%d)}%02d:%02d:%02d",
3768 r.right-5, r.bottom-3, hmsf.bHours, hmsf.bMinutes, hmsf.bSeconds);
3769 rts.Add(str, true, 1, 2, _T("thumbs"));
3771 rts.Render(spd, 0, 25, bbox);
3773 BYTE* pData = NULL;
3774 long size = 0;
3775 if(!GetDIB(&pData, size)) return;
3777 BITMAPINFO* bi = (BITMAPINFO*)pData;
3779 if(bi->bmiHeader.biBitCount != 32)
3781 delete [] pData;
3782 CString str;
3783 str.Format(_T("Invalid image format, cannot create thumbnails out of %d bpp dibs."), bi->bmiHeader.biBitCount);
3784 AfxMessageBox(str);
3785 return;
3788 int sw = bi->bmiHeader.biWidth;
3789 int sh = abs(bi->bmiHeader.biHeight);
3790 int sp = sw*4;
3791 const BYTE* src = pData + sizeof(bi->bmiHeader);
3792 if(bi->bmiHeader.biHeight >= 0) {src += sp*(sh-1); sp = -sp;}
3794 int dw = spd.w;
3795 int dh = spd.h;
3796 int dp = spd.pitch;
3797 BYTE* dst = (BYTE*)spd.bits + spd.pitch*r.top + r.left*4;
3799 for(DWORD h = r.bottom - r.top, y = 0, yd = (sh<<8)/h; h > 0; y += yd, h--)
3801 DWORD yf = y&0xff;
3802 DWORD yi = y>>8;
3804 DWORD* s0 = (DWORD*)(src + yi*sp);
3805 DWORD* s1 = (DWORD*)(src + yi*sp + sp);
3806 DWORD* d = (DWORD*)dst;
3808 for(DWORD w = r.right - r.left, x = 0, xd = (sw<<8)/w; w > 0; x += xd, w--)
3810 DWORD xf = x&0xff;
3811 DWORD xi = x>>8;
3813 DWORD c0 = s0[xi];
3814 DWORD c1 = s0[xi+1];
3815 DWORD c2 = s1[xi];
3816 DWORD c3 = s1[xi+1];
3818 c0 = ((c0&0xff00ff) + ((((c1&0xff00ff) - (c0&0xff00ff)) * xf) >> 8)) & 0xff00ff
3819 | ((c0&0x00ff00) + ((((c1&0x00ff00) - (c0&0x00ff00)) * xf) >> 8)) & 0x00ff00;
3821 c2 = ((c2&0xff00ff) + ((((c3&0xff00ff) - (c2&0xff00ff)) * xf) >> 8)) & 0xff00ff
3822 | ((c2&0x00ff00) + ((((c3&0x00ff00) - (c2&0x00ff00)) * xf) >> 8)) & 0x00ff00;
3824 c0 = ((c0&0xff00ff) + ((((c2&0xff00ff) - (c0&0xff00ff)) * yf) >> 8)) & 0xff00ff
3825 | ((c0&0x00ff00) + ((((c2&0x00ff00) - (c0&0x00ff00)) * yf) >> 8)) & 0x00ff00;
3827 *d++ = c0;
3830 dst += dp;
3833 rts.Render(spd, 10000, 25, bbox);
3835 delete [] pData;
3839 CRenderedTextSubtitle rts(&csSubLock);
3840 rts.CreateDefaultStyle(0);
3841 rts.m_dstScreenSize.SetSize(width, height);
3842 STSStyle* style = new STSStyle();
3843 style->marginRect.SetRect(margin*2, margin*2, margin*2, height-infoheight-margin);
3844 rts.AddStyle(_T("thumbs"), style);
3846 CStringW str;
3847 str.Format(L"{\\an9\\fs%d\\b1\\bord0\\shad0\\1c&Hffffff&}%s", infoheight-10, width >= 550 ? L"Media Player Classic" : L"MPC");
3849 rts.Add(str, true, 0, 1, _T("thumbs"), _T(""), _T(""), CRect(0,0,0,0), -1);
3851 DVD_HMSF_TIMECODE hmsf = RT2HMSF(rtDur, 25);
3853 CPath path(m_wndPlaylistBar.GetCur());
3854 path.StripPath();
3855 CStringW fn = (LPCTSTR)path;
3857 CStringW fs;
3858 WIN32_FIND_DATA wfd;
3859 HANDLE hFind = FindFirstFile(m_wndPlaylistBar.GetCur(), &wfd);
3860 if(hFind != INVALID_HANDLE_VALUE)
3862 FindClose(hFind);
3864 __int64 size = (__int64(wfd.nFileSizeHigh)<<32)|wfd.nFileSizeLow;
3865 __int64 shortsize = size;
3866 CStringW measure = _T("B");
3867 if(shortsize > 10240) shortsize /= 1024, measure = L"KB";
3868 if(shortsize > 10240) shortsize /= 1024, measure = L"MB";
3869 if(shortsize > 10240) shortsize /= 1024, measure = L"GB";
3870 fs.Format(L"File Size: %I64d%s (%I64d bytes)\\N", shortsize, measure, size);
3873 CStringW ar;
3874 if(arxy.cx > 0 && arxy.cy > 0 && arxy.cx != wh.cx && arxy.cy != wh.cy)
3875 ar.Format(L"(%d:%d)", arxy.cx, arxy.cy);
3877 str.Format(L"{\\an7\\1c&H000000&\\fs16\\b0\\bord0\\shad0}File Name: %s\\N%sResolution: %dx%d %s\\NDuration: %02d:%02d:%02d",
3878 fn, fs, wh.cx, wh.cy, ar, hmsf.bHours, hmsf.bMinutes, hmsf.bSeconds);
3879 rts.Add(str, true, 0, 1, _T("thumbs"));
3881 rts.Render(spd, 0, 25, bbox);
3884 SaveDIB(fn, (BYTE*)dib, dibsize);
3886 SeekTo(rtPos);
3889 static CString MakeSnapshotFileName(LPCTSTR prefix)
3891 CTime t = CTime::GetCurrentTime();
3892 CString fn;
3893 fn.Format(_T("%s%s%s"), prefix, t.Format(_T("%Y%m%d%H%M%S")), AfxGetAppSettings().SnapShotExt);
3894 return fn;
3897 BOOL CMainFrame::IsRendererCompatibleWithSaveImage()
3899 BOOL result = TRUE;
3900 AppSettings& s = AfxGetAppSettings();
3902 if(m_fRealMediaGraph) {
3903 if(s.iRMVideoRendererType == VIDRNDT_RM_DEFAULT) {
3904 AfxMessageBox(_T("The 'Save Image' and 'Save Thumbnails' functions do not work with the default video renderer for RealMedia.\nSelect one of the DirectX renderers for RealMedia in MPC's output options and reopen the file."));
3905 result = FALSE;
3907 } else {
3908 if(m_fQuicktimeGraph) {
3909 if(s.iQTVideoRendererType == VIDRNDT_QT_DEFAULT) {
3910 AfxMessageBox(_T("The 'Save Image and 'Save Thumbnails' functions do not work with the default video renderer for QuickTime.\nSelect one of the DirectX renderers for QuickTime in MPC's output options and reopen the file."));
3911 result = FALSE;
3913 } else {
3914 if(m_fShockwaveGraph) {
3915 AfxMessageBox(_T("The 'Save Image' and 'Save Thumbnails' functions do not work for Shockwave files."));
3916 result = FALSE;
3917 } else {
3918 if(s.iDSVideoRendererType == VIDRNDT_DS_OVERLAYMIXER) {
3919 AfxMessageBox(_T("The 'Save Image' and 'Save Thumbnails' functions do not work with the Overlay Mixer video renderer.\nChange the video renderer in MPC's output options and reopen the file."));
3920 result = FALSE;
3925 return result;
3928 void CMainFrame::OnFileSaveImage()
3930 AppSettings& s = AfxGetAppSettings();
3932 /* Check if a compatible renderer is being used */
3933 if(!IsRendererCompatibleWithSaveImage()) {
3934 return;
3937 CPath psrc(s.SnapShotPath);
3938 psrc.Combine(s.SnapShotPath, MakeSnapshotFileName(_T("snapshot")));
3940 CFileDialog fd(FALSE, 0, (LPCTSTR)psrc,
3941 OFN_EXPLORER|OFN_ENABLESIZING|OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_PATHMUSTEXIST,
3942 _T("Bitmaps (*.bmp)|*.bmp|Jpeg (*.jpg)|*.jpg|Png (*.png)|*.png||"), this, 0);
3944 if(s.SnapShotExt == _T(".bmp")) fd.m_pOFN->nFilterIndex = 1;
3945 else if(s.SnapShotExt == _T(".jpg")) fd.m_pOFN->nFilterIndex = 2;
3946 else if(s.SnapShotExt == _T(".png")) fd.m_pOFN->nFilterIndex = 3;
3948 if(fd.DoModal() != IDOK) return;
3950 if(fd.m_pOFN->nFilterIndex == 1) s.SnapShotExt = _T(".bmp");
3951 else if(fd.m_pOFN->nFilterIndex == 2) s.SnapShotExt = _T(".jpg");
3952 else if(fd.m_pOFN->nFilterIndex = 3) s.SnapShotExt = _T(".png");
3954 CPath pdst(fd.GetPathName());
3955 if(pdst.GetExtension().MakeLower() != s.SnapShotExt) pdst = CPath((LPCTSTR)pdst + s.SnapShotExt);
3956 CString path = (LPCTSTR)pdst;
3957 pdst.RemoveFileSpec();
3958 s.SnapShotPath = (LPCTSTR)pdst;
3960 SaveImage(path);
3963 void CMainFrame::OnFileSaveImageAuto()
3965 AppSettings& s = AfxGetAppSettings();
3967 /* Check if a compatible renderer is being used */
3968 if(!IsRendererCompatibleWithSaveImage()) {
3969 return;
3972 CString fn;
3973 fn.Format(_T("%s\\%s"), AfxGetAppSettings().SnapShotPath, MakeSnapshotFileName(_T("snapshot")));
3974 SaveImage(fn);
3977 void CMainFrame::OnUpdateFileSaveImage(CCmdUI* pCmdUI)
3979 OAFilterState fs = GetMediaState();
3980 pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly && (fs == State_Paused || fs == State_Running));
3983 void CMainFrame::OnFileSaveThumbnails()
3985 AppSettings& s = AfxGetAppSettings();
3987 /* Check if a compatible renderer is being used */
3988 if(!IsRendererCompatibleWithSaveImage()) {
3989 return;
3992 CPath psrc(s.SnapShotPath);
3993 psrc.Combine(s.SnapShotPath, MakeSnapshotFileName(_T("thumbs")));
3995 CSaveThumbnailsDialog fd(
3996 s.ThumbRows, s.ThumbCols, s.ThumbWidth,
3997 0, (LPCTSTR)psrc,
3998 _T("Bitmaps (*.bmp)|*.bmp|Jpeg (*.jpg)|*.jpg|Png (*.png)|*.png||"), this);
4000 if(s.SnapShotExt == _T(".bmp")) fd.m_pOFN->nFilterIndex = 1;
4001 else if(s.SnapShotExt == _T(".jpg")) fd.m_pOFN->nFilterIndex = 2;
4002 else if(s.SnapShotExt == _T(".png")) fd.m_pOFN->nFilterIndex = 3;
4004 if(fd.DoModal() != IDOK) return;
4006 if(fd.m_pOFN->nFilterIndex == 1) s.SnapShotExt = _T(".bmp");
4007 else if(fd.m_pOFN->nFilterIndex == 2) s.SnapShotExt = _T(".jpg");
4008 else if(fd.m_pOFN->nFilterIndex = 3) s.SnapShotExt = _T(".png");
4010 s.ThumbRows = fd.m_rows;
4011 s.ThumbCols = fd.m_cols;
4012 s.ThumbWidth = fd.m_width;
4014 CPath pdst(fd.GetPathName());
4015 if(pdst.GetExtension().MakeLower() != s.SnapShotExt) pdst = CPath((LPCTSTR)pdst + s.SnapShotExt);
4016 CString path = (LPCTSTR)pdst;
4017 pdst.RemoveFileSpec();
4018 s.SnapShotPath = (LPCTSTR)pdst;
4020 SaveThumbnails(path);
4023 void CMainFrame::OnUpdateFileSaveThumbnails(CCmdUI* pCmdUI)
4025 OAFilterState fs = GetMediaState();
4026 pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly && (m_iPlaybackMode == PM_FILE /*|| m_iPlaybackMode == PM_DVD*/));
4029 void CMainFrame::OnFileConvert()
4031 CConvertDlg().DoModal();
4034 void CMainFrame::OnUpdateFileConvert(CCmdUI* pCmdUI)
4036 // TODO: Add your command update UI handler code here
4039 void CMainFrame::OnFileLoadsubtitle()
4041 #ifndef DEBUG
4042 if(!m_pCAP)
4044 AfxMessageBox(_T("To load subtitles you have change the video renderer and reopen the file.\n")
4045 _T("- DirectShow: VMR7/VMR9(renderless) or Haali Video Renderer\n")
4046 _T("- RealMedia: Special renderer for RealMedia, or open it through DirectShow\n")
4047 _T("- Quicktime: DX7 or DX9 renderer for QuickTime\n")
4048 , MB_OK);
4049 return;
4051 #endif
4052 static TCHAR BASED_CODE szFilter[] =
4053 _T(".srt .sub .ssa .ass .smi .psb .txt .idx .usf .xss .ssf|")
4054 _T("*.srt;*.sub;*.ssa;*.ass;*smi;*.psb;*.txt;*.idx;*.usf;*.xss;*.ssf|")
4055 _T("All files (*.*)|")
4056 _T("*.*||");
4058 CFileDialog fd(TRUE, NULL, NULL,
4059 OFN_EXPLORER | OFN_ENABLESIZING | OFN_HIDEREADONLY,
4060 szFilter, this, 0);
4062 if(fd.DoModal() != IDOK) return;
4064 if(LoadSubtitle(fd.GetPathName()))
4065 SetSubtitle(m_pSubStreams.GetTail());
4068 void CMainFrame::OnUpdateFileLoadsubtitle(CCmdUI *pCmdUI)
4070 #ifdef DEBUG
4071 pCmdUI->Enable();
4072 #else
4073 pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && /*m_pCAP &&*/ !m_fAudioOnly);
4074 #endif
4077 void CMainFrame::OnFileSavesubtitle()
4079 int i = m_iSubtitleSel;
4081 POSITION pos = m_pSubStreams.GetHeadPosition();
4082 while(pos && i >= 0)
4084 CComPtr<ISubStream> pSubStream = m_pSubStreams.GetNext(pos);
4086 if(i < pSubStream->GetStreamCount())
4088 CLSID clsid;
4089 if(FAILED(pSubStream->GetClassID(&clsid)))
4090 continue;
4092 if(clsid == __uuidof(CVobSubFile))
4094 CVobSubFile* pVSF = (CVobSubFile*)(ISubStream*)pSubStream;
4096 CFileDialog fd(FALSE, NULL, NULL,
4097 OFN_EXPLORER|OFN_ENABLESIZING|OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_PATHMUSTEXIST,
4098 _T("VobSub (*.idx, *.sub)|*.idx;*.sub||"), this, 0);
4100 if(fd.DoModal() == IDOK)
4102 CAutoLock cAutoLock(&m_csSubLock);
4103 pVSF->Save(fd.GetPathName());
4106 return;
4108 else if(clsid == __uuidof(CRenderedTextSubtitle))
4110 CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)pSubStream;
4112 CString filter;
4113 filter += _T("Subripper (*.srt)|*.srt|");
4114 filter += _T("Microdvd (*.sub)|*.sub|");
4115 filter += _T("Sami (*.smi)|*.smi|");
4116 filter += _T("Psb (*.psb)|*.psb|");
4117 filter += _T("Sub Station Alpha (*.ssa)|*.ssa|");
4118 filter += _T("Advanced Sub Station Alpha (*.ass)|*.ass|");
4119 filter += _T("|");
4121 CSaveTextFileDialog fd(pRTS->m_encoding, NULL, NULL, filter, this);
4123 if(fd.DoModal() == IDOK)
4125 CAutoLock cAutoLock(&m_csSubLock);
4126 pRTS->SaveAs(fd.GetPathName(), (exttype)(fd.m_ofn.nFilterIndex-1), m_pCAP->GetFPS(), fd.GetEncoding());
4129 return;
4133 i -= pSubStream->GetStreamCount();
4137 void CMainFrame::OnUpdateFileSavesubtitle(CCmdUI* pCmdUI)
4139 pCmdUI->Enable(m_iSubtitleSel >= 0);
4142 ///////////////
4144 #include "SubtitleDlDlg.h"
4145 #include "ISDb.h"
4147 void CMainFrame::OnFileISDBSearch()
4149 CStringA url = "http://" + AfxGetAppSettings().ISDb + "/index.php?";
4150 CStringA args = makeargs(m_wndPlaylistBar.m_pl);
4151 ShellExecute(m_hWnd, _T("open"), CString(url+args), NULL, NULL, SW_SHOWDEFAULT);
4154 void CMainFrame::OnUpdateFileISDBSearch(CCmdUI *pCmdUI)
4156 pCmdUI->Enable(TRUE);
4159 void CMainFrame::OnFileISDBUpload()
4161 CStringA url = "http://" + AfxGetAppSettings().ISDb + "/ul.php?";
4162 CStringA args = makeargs(m_wndPlaylistBar.m_pl);
4163 ShellExecute(m_hWnd, _T("open"), CString(url+args), NULL, NULL, SW_SHOWDEFAULT);
4166 void CMainFrame::OnUpdateFileISDBUpload(CCmdUI *pCmdUI)
4168 pCmdUI->Enable(m_wndPlaylistBar.GetCount() > 0);
4171 void CMainFrame::OnFileISDBDownload()
4173 filehash fh;
4174 if(!hash(m_wndPlaylistBar.GetCur(), fh))
4176 MessageBeep(-1);
4177 return;
4180 // TODO: put this on a worker thread
4182 CStringA url = "http://" + AfxGetAppSettings().ISDb + "/index.php?";
4183 CStringA args;
4184 args.Format("player=mpc&name[0]=%s&size[0]=%016I64x&hash[0]=%016I64x",
4185 UrlEncode(CStringA(fh.name)), fh.size, fh.hash);
4189 CInternetSession is;
4191 CStringA str;
4192 if(!OpenUrl(is, CString(url+args), str))
4194 MessageBeep(-1);
4195 return;
4198 CStringA ticket;
4199 CList<isdb_movie> movies;
4200 isdb_movie m;
4201 isdb_subtitle s;
4203 CAtlList<CStringA> sl;
4204 Explode(str, sl, '\n');
4206 POSITION pos = sl.GetHeadPosition();
4207 while(pos)
4209 str = sl.GetNext(pos);
4211 CStringA param = str.Left(max(0, str.Find('=')));
4212 CStringA value = str.Mid(str.Find('=')+1);
4214 if(param == "ticket") ticket = value;
4215 else if(param == "movie") {m.reset(); Explode(value, m.titles, '|');}
4216 else if(param == "subtitle") {s.reset(); s.id = atoi(value);}
4217 else if(param == "name") s.name = value;
4218 else if(param == "discs") s.discs = atoi(value);
4219 else if(param == "disc_no") s.disc_no = atoi(value);
4220 else if(param == "format") s.format = value;
4221 else if(param == "iso639_2") s.iso639_2 = value;
4222 else if(param == "language") s.language = value;
4223 else if(param == "nick") s.nick = value;
4224 else if(param == "email") s.email = value;
4225 else if(param == "" && value == "endsubtitle") {m.subs.AddTail(s);}
4226 else if(param == "" && value == "endmovie") {movies.AddTail(m);}
4227 else if(param == "" && value == "end") break;
4230 CSubtitleDlDlg dlg(movies, this);
4231 if(IDOK == dlg.DoModal())
4233 if(dlg.m_fReplaceSubs)
4234 m_pSubStreams.RemoveAll();
4236 CComPtr<ISubStream> pSubStreamToSet;
4238 POSITION pos = dlg.m_selsubs.GetHeadPosition();
4239 while(pos)
4241 isdb_subtitle& s = dlg.m_selsubs.GetNext(pos);
4243 CStringA url = "http://" + AfxGetAppSettings().ISDb + "/dl.php?";
4244 CStringA args;
4245 args.Format("id=%d&ticket=%s", s.id, UrlEncode(ticket));
4247 if(OpenUrl(is, CString(url+args), str))
4249 CAutoPtr<CRenderedTextSubtitle> pRTS(new CRenderedTextSubtitle(&m_csSubLock));
4250 if(pRTS && pRTS->Open((BYTE*)(LPCSTR)str, str.GetLength(), DEFAULT_CHARSET, CString(s.name)) && pRTS->GetStreamCount() > 0)
4252 CComPtr<ISubStream> pSubStream = pRTS.Detach();
4253 m_pSubStreams.AddTail(pSubStream);
4254 if(!pSubStreamToSet) pSubStreamToSet = pSubStream;
4259 if(pSubStreamToSet)
4260 SetSubtitle(pSubStreamToSet);
4263 catch(CInternetException* ie)
4265 ie->Delete();
4266 return;
4270 void CMainFrame::OnUpdateFileISDBDownload(CCmdUI *pCmdUI)
4272 pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && m_pCAP && !m_fAudioOnly);
4275 void CMainFrame::OnFileProperties()
4277 CPPageFileInfoSheet m_fileinfo(m_wndPlaylistBar.GetCur(), this);
4278 m_fileinfo.DoModal();
4281 void CMainFrame::OnUpdateFileProperties(CCmdUI* pCmdUI)
4283 pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && m_iPlaybackMode == PM_FILE);
4286 void CMainFrame::OnFileCloseMedia()
4288 CloseMedia();
4291 void CMainFrame::OnFileClosePlaylist()
4293 SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
4294 RestoreDefaultWindowRect();
4297 void CMainFrame::OnUpdateFileClose(CCmdUI* pCmdUI)
4299 pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED || m_iMediaLoadState == MLS_LOADING);
4302 // view
4304 void CMainFrame::OnViewCaptionmenu()
4306 bool fHideCaptionMenu = AfxGetAppSettings().fHideCaptionMenu;
4308 AfxGetAppSettings().fHideCaptionMenu = !fHideCaptionMenu;
4310 if(m_fFullScreen) return;
4312 DWORD dwRemove = 0, dwAdd = 0;
4313 HMENU hMenu;
4315 if(!fHideCaptionMenu)
4317 dwRemove = WS_CAPTION;
4318 hMenu = NULL;
4320 else
4322 dwAdd = WS_CAPTION;
4323 hMenu = m_hMenuDefault;
4326 ModifyStyle(dwRemove, dwAdd, SWP_NOZORDER);
4327 ::SetMenu(m_hWnd, hMenu);
4328 SetWindowPos(NULL, 0, 0, 0, 0, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER);
4330 MoveVideoWindow();
4333 void CMainFrame::OnUpdateViewCaptionmenu(CCmdUI* pCmdUI)
4335 pCmdUI->SetCheck(!AfxGetAppSettings().fHideCaptionMenu);
4338 void CMainFrame::OnViewControlBar(UINT nID)
4340 nID -= ID_VIEW_SEEKER;
4341 ShowControls(AfxGetAppSettings().nCS ^ (1<<nID));
4344 void CMainFrame::OnUpdateViewControlBar(CCmdUI* pCmdUI)
4346 UINT nID = pCmdUI->m_nID - ID_VIEW_SEEKER;
4347 pCmdUI->SetCheck(!!(AfxGetAppSettings().nCS & (1<<nID)));
4350 void CMainFrame::OnViewSubresync()
4352 ShowControlBar(&m_wndSubresyncBar, !m_wndSubresyncBar.IsWindowVisible(), TRUE);
4355 void CMainFrame::OnUpdateViewSubresync(CCmdUI* pCmdUI)
4357 pCmdUI->SetCheck(m_wndSubresyncBar.IsWindowVisible());
4358 pCmdUI->Enable(m_pCAP && m_iSubtitleSel >= 0);
4361 void CMainFrame::OnViewPlaylist()
4363 ShowControlBar(&m_wndPlaylistBar, !m_wndPlaylistBar.IsWindowVisible(), TRUE);
4366 void CMainFrame::OnUpdateViewPlaylist(CCmdUI* pCmdUI)
4368 pCmdUI->SetCheck(m_wndPlaylistBar.IsWindowVisible());
4369 pCmdUI->Enable(m_iMediaLoadState == MLS_CLOSED && m_iMediaLoadState != MLS_LOADED
4370 || m_iMediaLoadState == MLS_LOADED /*&& (m_iPlaybackMode == PM_FILE || m_iPlaybackMode == PM_CAPTURE)*/);
4373 void CMainFrame::OnViewCapture()
4375 ShowControlBar(&m_wndCaptureBar, !m_wndCaptureBar.IsWindowVisible(), TRUE);
4378 void CMainFrame::OnUpdateViewCapture(CCmdUI* pCmdUI)
4380 pCmdUI->SetCheck(m_wndCaptureBar.IsWindowVisible());
4381 pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && m_iPlaybackMode == PM_CAPTURE);
4384 void CMainFrame::OnViewShaderEditor()
4386 ShowControlBar(&m_wndShaderEditorBar, !m_wndShaderEditorBar.IsWindowVisible(), TRUE);
4389 void CMainFrame::OnUpdateViewShaderEditor(CCmdUI* pCmdUI)
4391 pCmdUI->SetCheck(m_wndShaderEditorBar.IsWindowVisible());
4392 pCmdUI->Enable(TRUE);
4395 void CMainFrame::OnViewMinimal()
4397 if(!AfxGetAppSettings().fHideCaptionMenu)
4398 SendMessage(WM_COMMAND, ID_VIEW_CAPTIONMENU);
4399 ShowControls(0);
4402 void CMainFrame::OnUpdateViewMinimal(CCmdUI* pCmdUI)
4406 void CMainFrame::OnViewCompact()
4408 if(AfxGetAppSettings().fHideCaptionMenu)
4409 SendMessage(WM_COMMAND, ID_VIEW_CAPTIONMENU);
4410 ShowControls(CS_TOOLBAR);
4413 void CMainFrame::OnUpdateViewCompact(CCmdUI* pCmdUI)
4417 void CMainFrame::OnViewNormal()
4419 if(AfxGetAppSettings().fHideCaptionMenu)
4420 SendMessage(WM_COMMAND, ID_VIEW_CAPTIONMENU);
4421 ShowControls(CS_SEEKBAR|CS_TOOLBAR|CS_STATUSBAR|CS_INFOBAR);
4424 void CMainFrame::OnUpdateViewNormal(CCmdUI* pCmdUI)
4428 void CMainFrame::OnViewFullscreen()
4430 ToggleFullscreen(true, true);
4433 void CMainFrame::OnViewFullscreenSecondary()
4435 ToggleFullscreen(true, false);
4438 void CMainFrame::OnUpdateViewFullscreen(CCmdUI* pCmdUI)
4440 pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly || m_fFullScreen);
4441 pCmdUI->SetCheck(m_fFullScreen);
4444 void CMainFrame::OnViewZoom(UINT nID)
4446 ZoomVideoWindow(nID == ID_VIEW_ZOOM_50 ? 0.5 : nID == ID_VIEW_ZOOM_200 ? 2.0 : 1.0);
4449 void CMainFrame::OnUpdateViewZoom(CCmdUI* pCmdUI)
4451 pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly);
4454 void CMainFrame::OnViewZoomAutoFit()
4456 ZoomVideoWindow(GetZoomAutoFitScale());
4459 void CMainFrame::OnViewDefaultVideoFrame(UINT nID)
4461 AfxGetAppSettings().iDefaultVideoSize = nID - ID_VIEW_VF_HALF;
4462 m_ZoomX = m_ZoomY = 1;
4463 m_PosX = m_PosY = 0.5;
4464 MoveVideoWindow();
4467 void CMainFrame::OnUpdateViewDefaultVideoFrame(CCmdUI* pCmdUI)
4469 pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly);
4470 pCmdUI->SetRadio(AfxGetAppSettings().iDefaultVideoSize == (pCmdUI->m_nID - ID_VIEW_VF_HALF));
4473 void CMainFrame::OnViewKeepaspectratio()
4475 AfxGetAppSettings().fKeepAspectRatio = !AfxGetAppSettings().fKeepAspectRatio;
4476 MoveVideoWindow();
4479 void CMainFrame::OnUpdateViewKeepaspectratio(CCmdUI* pCmdUI)
4481 pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly);
4482 pCmdUI->SetCheck(AfxGetAppSettings().fKeepAspectRatio);
4485 void CMainFrame::OnViewCompMonDeskARDiff()
4487 AfxGetAppSettings().fCompMonDeskARDiff = !AfxGetAppSettings().fCompMonDeskARDiff;
4488 MoveVideoWindow();
4491 void CMainFrame::OnUpdateViewCompMonDeskARDiff(CCmdUI* pCmdUI)
4493 pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly);
4494 pCmdUI->SetCheck(AfxGetAppSettings().fCompMonDeskARDiff);
4497 void CMainFrame::OnViewPanNScan(UINT nID)
4499 if(m_iMediaLoadState != MLS_LOADED) return;
4501 int x = 0, y = 0;
4502 int dx = 0, dy = 0;
4504 switch(nID)
4506 case ID_VIEW_RESET: m_ZoomX = m_ZoomY = 1.0; m_PosX = m_PosY = 0.5; m_AngleX = m_AngleY = m_AngleZ = 0; break;
4507 case ID_VIEW_INCSIZE: x = y = 1; break;
4508 case ID_VIEW_DECSIZE: x = y = -1; break;
4509 case ID_VIEW_INCWIDTH: x = 1; break;
4510 case ID_VIEW_DECWIDTH: x = -1; break;
4511 case ID_VIEW_INCHEIGHT: y = 1; break;
4512 case ID_VIEW_DECHEIGHT: y = -1; break;
4513 case ID_PANSCAN_CENTER: m_PosX = m_PosY = 0.5; break;
4514 case ID_PANSCAN_MOVELEFT: dx = -1; break;
4515 case ID_PANSCAN_MOVERIGHT: dx = 1; break;
4516 case ID_PANSCAN_MOVEUP: dy = -1; break;
4517 case ID_PANSCAN_MOVEDOWN: dy = 1; break;
4518 case ID_PANSCAN_MOVEUPLEFT: dx = dy = -1; break;
4519 case ID_PANSCAN_MOVEUPRIGHT: dx = 1; dy = -1; break;
4520 case ID_PANSCAN_MOVEDOWNLEFT: dx = -1; dy = 1; break;
4521 case ID_PANSCAN_MOVEDOWNRIGHT: dx = dy = 1; break;
4522 default: break;
4525 if(x > 0 && m_ZoomX < 3) m_ZoomX *= 1.02;
4526 if(x < 0 && m_ZoomX > 0.2) m_ZoomX /= 1.02;
4527 if(y > 0 && m_ZoomY < 3) m_ZoomY *= 1.02;
4528 if(y < 0 && m_ZoomY > 0.2) m_ZoomY /= 1.02;
4530 if(dx < 0 && m_PosX > 0) m_PosX = max(m_PosX - 0.005*m_ZoomX, 0);
4531 if(dx > 0 && m_PosX < 1) m_PosX = min(m_PosX + 0.005*m_ZoomX, 1);
4532 if(dy < 0 && m_PosY > 0) m_PosY = max(m_PosY - 0.005*m_ZoomY, 0);
4533 if(dy > 0 && m_PosY < 1) m_PosY = min(m_PosY + 0.005*m_ZoomY, 1);
4535 MoveVideoWindow(true);
4538 void CMainFrame::OnUpdateViewPanNScan(CCmdUI* pCmdUI)
4540 pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly);
4543 void CMainFrame::OnViewPanNScanPresets(UINT nID)
4545 if(m_iMediaLoadState != MLS_LOADED) return;
4547 AppSettings& s = AfxGetAppSettings();
4549 nID -= ID_PANNSCAN_PRESETS_START;
4551 if(nID == s.m_pnspresets.GetCount())
4553 CPnSPresetsDlg dlg;
4554 dlg.m_pnspresets.Copy(s.m_pnspresets);
4555 if(dlg.DoModal() == IDOK)
4557 s.m_pnspresets.Copy(dlg.m_pnspresets);
4558 s.UpdateData(true);
4560 return;
4563 m_PosX = 0.5;
4564 m_PosY = 0.5;
4565 m_ZoomX = 1.0;
4566 m_ZoomY = 1.0;
4568 CString str = s.m_pnspresets[nID];
4570 int i = 0, j = 0;
4571 for(CString token = str.Tokenize(_T(","), i); !token.IsEmpty(); token = str.Tokenize(_T(","), i), j++)
4573 float f = 0;
4574 if(_stscanf(token, _T("%f"), &f) != 1) continue;
4576 switch(j)
4578 case 0: break;
4579 case 1: m_PosX = f; break;
4580 case 2: m_PosY = f; break;
4581 case 3: m_ZoomX = f; break;
4582 case 4: m_ZoomY = f; break;
4583 default: break;
4587 if(j != 5) return;
4589 m_PosX = min(max(m_PosX, 0), 1);
4590 m_PosY = min(max(m_PosY, 0), 1);
4591 m_ZoomX = min(max(m_ZoomX, 0.2), 3);
4592 m_ZoomY = min(max(m_ZoomY, 0.2), 3);
4594 MoveVideoWindow(true);
4597 void CMainFrame::OnUpdateViewPanNScanPresets(CCmdUI* pCmdUI)
4599 int nID = pCmdUI->m_nID - ID_PANNSCAN_PRESETS_START;
4600 AppSettings& s = AfxGetAppSettings();
4601 pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly && nID >= 0 && nID <= s.m_pnspresets.GetCount());
4604 void CMainFrame::OnViewRotate(UINT nID)
4606 if(!m_pCAP) return;
4608 switch(nID)
4610 case ID_PANSCAN_ROTATEXP: m_AngleX += 2; break;
4611 case ID_PANSCAN_ROTATEXM: m_AngleX -= 2; break;
4612 case ID_PANSCAN_ROTATEYP: m_AngleY += 2; break;
4613 case ID_PANSCAN_ROTATEYM: m_AngleY -= 2; break;
4614 case ID_PANSCAN_ROTATEZP: m_AngleZ += 2; break;
4615 case ID_PANSCAN_ROTATEZM: m_AngleZ -= 2; break;
4616 default: return;
4619 m_pCAP->SetVideoAngle(Vector(DegToRad(m_AngleX), DegToRad(m_AngleY), DegToRad(m_AngleZ)));
4621 CString info;
4622 info.Format(_T("x: %d, y: %d, z: %d"), m_AngleX, m_AngleY, m_AngleZ);
4623 SendStatusMessage(info, 3000);
4626 void CMainFrame::OnUpdateViewRotate(CCmdUI* pCmdUI)
4628 pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly && m_pCAP);
4631 // FIXME
4632 const static SIZE s_ar[] = {{0,0}, {4,3}, {5,4}, {16,9}};
4634 void CMainFrame::OnViewAspectRatio(UINT nID)
4636 CSize& ar = AfxGetAppSettings().AspectRatio;
4638 ar = s_ar[nID - ID_ASPECTRATIO_START];
4640 CString info;
4641 if(ar.cx && ar.cy) info.Format(_T("Aspect Ratio: %d:%d"), ar.cx, ar.cy);
4642 else info.Format(_T("Aspect Ratio: Default"));
4643 SendStatusMessage(info, 3000);
4645 MoveVideoWindow();
4648 void CMainFrame::OnUpdateViewAspectRatio(CCmdUI* pCmdUI)
4650 pCmdUI->SetRadio(AfxGetAppSettings().AspectRatio == s_ar[pCmdUI->m_nID - ID_ASPECTRATIO_START]);
4651 pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly);
4654 void CMainFrame::OnViewAspectRatioNext()
4656 CSize& ar = AfxGetAppSettings().AspectRatio;
4658 UINT nID = ID_ASPECTRATIO_START;
4660 for(int i = 0; i < countof(s_ar); i++)
4662 if(ar == s_ar[i])
4664 nID += (i + 1) % countof(s_ar);
4665 break;
4669 OnViewAspectRatio(nID);
4672 void CMainFrame::OnViewOntop(UINT nID)
4674 nID -= ID_ONTOP_NEVER;
4675 if(AfxGetAppSettings().iOnTop == nID)
4676 nID = !nID;
4677 SetAlwaysOnTop(nID);
4680 void CMainFrame::OnUpdateViewOntop(CCmdUI* pCmdUI)
4682 pCmdUI->SetRadio(AfxGetAppSettings().iOnTop == (pCmdUI->m_nID - ID_ONTOP_NEVER));
4685 void CMainFrame::OnViewOptions()
4687 ShowOptions();
4690 // play
4692 void CMainFrame::OnPlayPlay()
4694 if(m_iMediaLoadState == MLS_LOADED)
4696 if(GetMediaState() == State_Stopped) m_iSpeedLevel = 0;
4698 if(m_iPlaybackMode == PM_FILE)
4700 if(m_fEndOfStream) SendMessage(WM_COMMAND, ID_PLAY_STOP);
4701 pMC->Run();
4703 else if(m_iPlaybackMode == PM_DVD)
4705 double dRate = 1.0;
4706 if(m_iSpeedLevel != -4 && m_iSpeedLevel != 0)
4707 dRate = pow(2.0, m_iSpeedLevel >= -3 ? m_iSpeedLevel : (-m_iSpeedLevel - 8));
4709 pDVDC->PlayForwards(dRate, DVD_CMD_FLAG_Block, NULL);
4710 pDVDC->Pause(FALSE);
4711 pMC->Run();
4713 else if(m_iPlaybackMode == PM_CAPTURE)
4715 pMC->Stop(); // audio preview won't be in sync if we run it from paused state
4716 pMC->Run();
4719 SetTimer(TIMER_STREAMPOSPOLLER, 40, NULL);
4720 SetTimer(TIMER_STREAMPOSPOLLER2, 500, NULL);
4721 SetTimer(TIMER_STATS, 1000, NULL);
4723 if(m_fFrameSteppingActive) // FIXME
4725 m_fFrameSteppingActive = false;
4726 pBA->put_Volume(m_VolumeBeforeFrameStepping);
4729 SetAlwaysOnTop(AfxGetAppSettings().iOnTop);
4732 MoveVideoWindow();
4735 void CMainFrame::OnPlayPauseI()
4737 if(m_iMediaLoadState == MLS_LOADED)
4739 SetAlwaysOnTop(AfxGetAppSettings().iOnTop);
4741 if(m_iPlaybackMode == PM_FILE)
4743 pMC->Pause();
4745 else if(m_iPlaybackMode == PM_DVD)
4747 pMC->Pause();
4749 else if(m_iPlaybackMode == PM_CAPTURE)
4751 pMC->Pause();
4754 SetTimer(TIMER_STREAMPOSPOLLER, 40, NULL);
4755 SetTimer(TIMER_STREAMPOSPOLLER2, 500, NULL);
4756 SetTimer(TIMER_STATS, 1000, NULL);
4759 MoveVideoWindow();
4762 void CMainFrame::OnPlayPause()
4764 // Support ffdshow queueing.
4765 // To avoid black out on pause, we have to lock g_ffdshowReceive to synchronize with ReceiveMine.
4766 if(queueu_ffdshow_support)
4768 CAutoLock lck(&g_ffdshowReceive);
4769 return OnPlayPauseI();
4771 OnPlayPauseI();
4774 void CMainFrame::OnPlayPlaypause()
4776 OAFilterState fs = GetMediaState();
4777 if(fs == State_Running) SendMessage(WM_COMMAND, ID_PLAY_PAUSE);
4778 else if(fs == State_Stopped || fs == State_Paused) SendMessage(WM_COMMAND, ID_PLAY_PLAY);
4781 void CMainFrame::OnPlayStop()
4783 if(m_iMediaLoadState == MLS_LOADED)
4785 if(m_iPlaybackMode == PM_FILE)
4787 LONGLONG pos = 0;
4788 pMS->SetPositions(&pos, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning);
4789 pMC->Stop();
4791 // BUG: after pause or stop the netshow url source filter won't continue
4792 // on the next play command, unless we cheat it by setting the file name again.
4794 // Note: WMPx may be using some undocumented interface to restart streaming.
4796 BeginEnumFilters(pGB, pEF, pBF)
4798 CComQIPtr<IAMNetworkStatus, &IID_IAMNetworkStatus> pAMNS = pBF;
4799 CComQIPtr<IFileSourceFilter> pFSF = pBF;
4800 if(pAMNS && pFSF)
4802 WCHAR* pFN = NULL;
4803 AM_MEDIA_TYPE mt;
4804 if(SUCCEEDED(pFSF->GetCurFile(&pFN, &mt)) && pFN && *pFN)
4806 pFSF->Load(pFN, NULL);
4807 CoTaskMemFree(pFN);
4809 break;
4812 EndEnumFilters
4814 else if(m_iPlaybackMode == PM_DVD)
4816 pDVDC->SetOption(DVD_ResetOnStop, TRUE);
4817 pMC->Stop();
4818 pDVDC->SetOption(DVD_ResetOnStop, FALSE);
4820 else if(m_iPlaybackMode == PM_CAPTURE)
4822 pMC->Stop();
4825 m_iSpeedLevel = 0;
4827 if(m_fFrameSteppingActive) // FIXME
4829 m_fFrameSteppingActive = false;
4830 pBA->put_Volume(m_VolumeBeforeFrameStepping);
4833 m_fEndOfStream = false;
4836 m_nLoops = 0;
4838 if(m_hWnd)
4840 KillTimer(TIMER_STREAMPOSPOLLER2);
4841 KillTimer(TIMER_STREAMPOSPOLLER);
4842 KillTimer(TIMER_STATS);
4844 MoveVideoWindow();
4846 if(m_iMediaLoadState == MLS_LOADED)
4848 __int64 start, stop;
4849 m_wndSeekBar.GetRange(start, stop);
4850 GUID tf;
4851 pMS->GetTimeFormat(&tf);
4852 m_wndStatusBar.SetStatusTimer(m_wndSeekBar.GetPosReal(), stop, !!m_wndSubresyncBar.IsWindowVisible(), &tf);
4854 SetAlwaysOnTop(AfxGetAppSettings().iOnTop);
4859 void CMainFrame::OnUpdatePlayPauseStop(CCmdUI* pCmdUI)
4861 OAFilterState fs = m_fFrameSteppingActive ? State_Paused : GetMediaState();
4863 pCmdUI->SetCheck(fs == State_Running && pCmdUI->m_nID == ID_PLAY_PLAY
4864 || fs == State_Paused && pCmdUI->m_nID == ID_PLAY_PAUSE
4865 || fs == State_Stopped && pCmdUI->m_nID == ID_PLAY_STOP
4866 || (fs == State_Paused || fs == State_Running) && pCmdUI->m_nID == ID_PLAY_PLAYPAUSE);
4868 bool fEnable = false;
4870 if(fs >= 0)
4872 if(m_iPlaybackMode == PM_FILE || m_iPlaybackMode == PM_CAPTURE)
4874 fEnable = true;
4876 if(fs == State_Stopped && pCmdUI->m_nID == ID_PLAY_PAUSE && m_fRealMediaGraph) fEnable = false; // can't go into paused state from stopped with rm
4877 else if(m_fCapturing) fEnable = false;
4878 else if(m_fLiveWM && pCmdUI->m_nID == ID_PLAY_PAUSE) fEnable = false;
4880 else if(m_iPlaybackMode == PM_DVD)
4882 fEnable = m_iDVDDomain != DVD_DOMAIN_VideoManagerMenu
4883 && m_iDVDDomain != DVD_DOMAIN_VideoTitleSetMenu;
4885 if(fs == State_Stopped && pCmdUI->m_nID == ID_PLAY_PAUSE) fEnable = false;
4889 pCmdUI->Enable(fEnable);
4892 void CMainFrame::OnPlayFramestep(UINT nID)
4894 REFERENCE_TIME rt;
4896 if(pFS && m_fQuicktimeGraph)
4898 if(GetMediaState() != State_Paused && !queueu_ffdshow_support)
4899 SendMessage(WM_COMMAND, ID_PLAY_PAUSE);
4901 pFS->Step(nID == ID_PLAY_FRAMESTEP ? 1 : -1, NULL);
4903 else if(pFS && nID == ID_PLAY_FRAMESTEP)
4905 if(GetMediaState() != State_Paused)
4906 SendMessage(WM_COMMAND, ID_PLAY_PAUSE);
4908 m_fFrameSteppingActive = true;
4910 m_VolumeBeforeFrameStepping = m_wndToolBar.Volume;
4911 pBA->put_Volume(-10000);
4913 pFS->Step(1, NULL);
4915 else if(S_OK == pMS->IsFormatSupported(&TIME_FORMAT_FRAME))
4917 if(GetMediaState() != State_Paused)
4918 SendMessage(WM_COMMAND, ID_PLAY_PAUSE);
4920 pMS->SetTimeFormat(&TIME_FORMAT_FRAME);
4921 pMS->GetCurrentPosition(&rt);
4922 if(nID == ID_PLAY_FRAMESTEP) rt++;
4923 else if(nID == ID_PLAY_FRAMESTEPCANCEL) rt--;
4924 pMS->SetPositions(&rt, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning);
4925 pMS->SetTimeFormat(&TIME_FORMAT_MEDIA_TIME);
4929 void CMainFrame::OnUpdatePlayFramestep(CCmdUI* pCmdUI)
4931 bool fEnable = false;
4933 if(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly
4934 && (m_iPlaybackMode != PM_DVD || m_iDVDDomain == DVD_DOMAIN_Title)
4935 && m_iPlaybackMode != PM_CAPTURE
4936 && !m_fLiveWM)
4938 REFTIME AvgTimePerFrame = 0;
4939 if(S_OK == pMS->IsFormatSupported(&TIME_FORMAT_FRAME)
4940 || pCmdUI->m_nID == ID_PLAY_FRAMESTEP && pFS && pFS->CanStep(0, NULL) == S_OK
4941 || m_fQuicktimeGraph && pFS)
4943 fEnable = true;
4947 pCmdUI->Enable(fEnable);
4950 void CMainFrame::OnPlaySeek(UINT nID)
4952 AppSettings& s = AfxGetAppSettings();
4954 REFERENCE_TIME dt =
4955 nID == ID_PLAY_SEEKBACKWARDSMALL ? -10000i64*s.nJumpDistS :
4956 nID == ID_PLAY_SEEKFORWARDSMALL ? +10000i64*s.nJumpDistS :
4957 nID == ID_PLAY_SEEKBACKWARDMED ? -10000i64*s.nJumpDistM :
4958 nID == ID_PLAY_SEEKFORWARDMED ? +10000i64*s.nJumpDistM :
4959 nID == ID_PLAY_SEEKBACKWARDLARGE ? -10000i64*s.nJumpDistL :
4960 nID == ID_PLAY_SEEKFORWARDLARGE ? +10000i64*s.nJumpDistL :
4963 if(!dt) return;
4965 // HACK: the custom graph should support frame based seeking instead
4966 if(m_fShockwaveGraph) dt /= 10000i64*100;
4968 SeekTo(m_wndSeekBar.GetPos() + dt);
4971 static int rangebsearch(REFERENCE_TIME val, CAtlArray<REFERENCE_TIME>& rta)
4973 int i = 0, j = rta.GetCount() - 1, ret = -1;
4975 if(j >= 0 && val >= rta[j]) return(j);
4977 while(i < j)
4979 int mid = (i + j) >> 1;
4980 REFERENCE_TIME midt = rta[mid];
4981 if(val == midt) {ret = mid; break;}
4982 else if(val < midt) {ret = -1; if(j == mid) mid--; j = mid;}
4983 else if(val > midt) {ret = mid; if(i == mid) mid++; i = mid;}
4986 return(ret);
4989 void CMainFrame::OnPlaySeekKey(UINT nID)
4991 if(m_kfs.GetCount() > 0)
4993 HRESULT hr;
4995 if(GetMediaState() == State_Stopped)
4996 SendMessage(WM_COMMAND, ID_PLAY_PAUSE);
4998 REFERENCE_TIME rtCurrent, rtDur;
4999 hr = pMS->GetCurrentPosition(&rtCurrent);
5000 hr = pMS->GetDuration(&rtDur);
5002 int dec = 1;
5003 int i = rangebsearch(rtCurrent, m_kfs);
5004 if(i > 0) dec = (UINT)max(min(rtCurrent - m_kfs[i-1], 10000000), 0);
5006 rtCurrent =
5007 nID == ID_PLAY_SEEKKEYBACKWARD ? max(rtCurrent - dec, 0) :
5008 nID == ID_PLAY_SEEKKEYFORWARD ? rtCurrent : 0;
5010 i = rangebsearch(rtCurrent, m_kfs);
5012 if(nID == ID_PLAY_SEEKKEYBACKWARD)
5013 rtCurrent = m_kfs[max(i, 0)];
5014 else if(nID == ID_PLAY_SEEKKEYFORWARD && i < m_kfs.GetCount()-1)
5015 rtCurrent = m_kfs[i+1];
5016 else
5017 return;
5019 // HACK: if d3d or something changes fpu control word the values of
5020 // m_kfs may be different now (if it was asked again), adding a little
5021 // to the seek position eliminates this error usually.
5023 rtCurrent += 10;
5025 hr = pMS->SetPositions(
5026 &rtCurrent, AM_SEEKING_AbsolutePositioning|AM_SEEKING_SeekToKeyFrame,
5027 NULL, AM_SEEKING_NoPositioning);
5031 void CMainFrame::OnUpdatePlaySeek(CCmdUI* pCmdUI)
5033 bool fEnable = false;
5035 OAFilterState fs = GetMediaState();
5037 if(m_iMediaLoadState == MLS_LOADED && (fs == State_Paused || fs == State_Running))
5039 fEnable = true;
5040 if(m_iPlaybackMode == PM_DVD && (m_iDVDDomain != DVD_DOMAIN_Title || fs != State_Running)) fEnable = false;
5041 else if(m_iPlaybackMode == PM_CAPTURE) fEnable = false;
5044 pCmdUI->Enable(fEnable);
5047 void CMainFrame::OnPlayGoto()
5049 if(m_iMediaLoadState != MLS_LOADED)
5050 return;
5052 REFTIME atpf = 0;
5053 if(FAILED(pBV->get_AvgTimePerFrame(&atpf)) || atpf < 0)
5055 atpf = 0;
5057 BeginEnumFilters(pGB, pEF, pBF)
5059 if(atpf > 0) break;
5061 BeginEnumPins(pBF, pEP, pPin)
5063 if(atpf > 0) break;
5065 AM_MEDIA_TYPE mt;
5066 pPin->ConnectionMediaType(&mt);
5068 if(mt.majortype == MEDIATYPE_Video && mt.formattype == FORMAT_VideoInfo)
5070 atpf = (REFTIME)((VIDEOINFOHEADER*)mt.pbFormat)->AvgTimePerFrame / 10000000i64;
5072 else if(mt.majortype == MEDIATYPE_Video && mt.formattype == FORMAT_VideoInfo2)
5074 atpf = (REFTIME)((VIDEOINFOHEADER2*)mt.pbFormat)->AvgTimePerFrame / 10000000i64;
5077 EndEnumPins
5079 EndEnumFilters
5082 CGoToDlg dlg((int)(m_wndSeekBar.GetPos()/10000), atpf > 0 ? (float)(1.0/atpf) : 0);
5083 if(IDOK != dlg.DoModal() || dlg.m_time < 0) return;
5085 SeekTo(10000i64 * dlg.m_time);
5088 void CMainFrame::OnUpdateGoto(CCmdUI* pCmdUI)
5090 bool fEnable = false;
5092 if(m_iMediaLoadState == MLS_LOADED)
5094 fEnable = true;
5095 if(m_iPlaybackMode == PM_DVD && m_iDVDDomain != DVD_DOMAIN_Title) fEnable = false;
5096 else if(m_iPlaybackMode == PM_CAPTURE) fEnable = false;
5099 pCmdUI->Enable(fEnable);
5102 void CMainFrame::OnPlayChangeRate(UINT nID)
5104 if(m_iMediaLoadState != MLS_LOADED)
5105 return;
5107 if(m_iPlaybackMode == PM_CAPTURE)
5109 if(GetMediaState() != State_Running)
5110 SendMessage(WM_COMMAND, ID_PLAY_PLAY);
5112 long lChannelMin = 0, lChannelMax = 0;
5113 pAMTuner->ChannelMinMax(&lChannelMin, &lChannelMax);
5114 long lChannel = 0, lVivSub = 0, lAudSub = 0;
5115 pAMTuner->get_Channel(&lChannel, &lVivSub, &lAudSub);
5117 long lFreqOrg = 0, lFreqNew = -1;
5118 pAMTuner->get_VideoFrequency(&lFreqOrg);
5120 // long lSignalStrength;
5123 if(nID == ID_PLAY_DECRATE) lChannel--;
5124 else if(nID == ID_PLAY_INCRATE) lChannel++;
5126 // if(lChannel < lChannelMin) lChannel = lChannelMax;
5127 // if(lChannel > lChannelMax) lChannel = lChannelMin;
5129 if(lChannel < lChannelMin || lChannel > lChannelMax)
5130 break;
5132 if(FAILED(pAMTuner->put_Channel(lChannel, AMTUNER_SUBCHAN_DEFAULT, AMTUNER_SUBCHAN_DEFAULT)))
5133 break;
5135 long flFoundSignal;
5136 pAMTuner->AutoTune(lChannel, &flFoundSignal);
5138 pAMTuner->get_VideoFrequency(&lFreqNew);
5140 while(FALSE);
5141 /* SUCCEEDED(pAMTuner->SignalPresent(&lSignalStrength))
5142 && (lSignalStrength != AMTUNER_SIGNALPRESENT || lFreqNew == lFreqOrg));*/
5145 else
5147 int iNewSpeedLevel;
5149 if(nID == ID_PLAY_INCRATE) iNewSpeedLevel = m_iSpeedLevel+1;
5150 else if(nID == ID_PLAY_DECRATE) iNewSpeedLevel = m_iSpeedLevel-1;
5151 else return;
5153 HRESULT hr = E_FAIL;
5155 if(iNewSpeedLevel == -4)
5157 if(GetMediaState() != State_Paused)
5158 SendMessage(WM_COMMAND, ID_PLAY_PAUSE);
5160 if(GetMediaState() == State_Paused) hr = S_OK;
5162 else
5164 double dRate = pow(2.0, iNewSpeedLevel >= -3 ? iNewSpeedLevel : (-iNewSpeedLevel - 8));
5165 if(fabs(dRate - 1.0) < 0.01) dRate = 1.0;
5167 if(GetMediaState() != State_Running)
5168 SendMessage(WM_COMMAND, ID_PLAY_PLAY);
5170 if(m_iPlaybackMode == PM_FILE)
5172 hr = pMS->SetRate(dRate);
5174 else if(m_iPlaybackMode == PM_DVD)
5176 if(iNewSpeedLevel >= -3)
5177 hr = pDVDC->PlayForwards(dRate, DVD_CMD_FLAG_Block, NULL);
5178 else
5179 hr = pDVDC->PlayBackwards(dRate, DVD_CMD_FLAG_Block, NULL);
5183 if(SUCCEEDED(hr))
5184 m_iSpeedLevel = iNewSpeedLevel;
5188 void CMainFrame::OnUpdatePlayChangeRate(CCmdUI* pCmdUI)
5190 bool fEnable = false;
5192 if(m_iMediaLoadState == MLS_LOADED)
5194 bool fInc = pCmdUI->m_nID == ID_PLAY_INCRATE;
5196 fEnable = true;
5197 if(fInc && m_iSpeedLevel >= 3) fEnable = false;
5198 else if(!fInc && m_iPlaybackMode == PM_FILE && m_iSpeedLevel <= -4) fEnable = false;
5199 else if(!fInc && m_iPlaybackMode == PM_DVD && m_iSpeedLevel <= -11) fEnable = false;
5200 else if(m_iPlaybackMode == PM_DVD && m_iDVDDomain != DVD_DOMAIN_Title) fEnable = false;
5201 else if(m_fRealMediaGraph || m_fShockwaveGraph) fEnable = false;
5202 else if(m_iPlaybackMode == PM_CAPTURE && (!m_wndCaptureBar.m_capdlg.IsTunerActive() || m_fCapturing)) fEnable = false;
5203 else if(m_fLiveWM) fEnable = false;
5206 pCmdUI->Enable(fEnable);
5209 void CMainFrame::OnPlayResetRate()
5211 if(m_iMediaLoadState != MLS_LOADED)
5212 return;
5214 HRESULT hr = E_FAIL;
5216 if(GetMediaState() != State_Running)
5217 SendMessage(WM_COMMAND, ID_PLAY_PLAY);
5219 if(m_iPlaybackMode == PM_FILE)
5221 hr = pMS->SetRate(1.0);
5223 else if(m_iPlaybackMode == PM_DVD)
5225 hr = pDVDC->PlayForwards(1.0, DVD_CMD_FLAG_Block, NULL);
5228 if(SUCCEEDED(hr))
5229 m_iSpeedLevel = 0;
5232 void CMainFrame::OnUpdatePlayResetRate(CCmdUI* pCmdUI)
5234 pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED);
5237 void CMainFrame::SetSubtitleDelay(int delay_ms)
5239 if(m_pCAP) {
5240 m_pCAP->SetSubtitleDelay(delay_ms);
5244 void CMainFrame::OnPlayChangeAudDelay(UINT nID)
5246 if(CComQIPtr<IAudioSwitcherFilter> pASF = FindFilter(__uuidof(CAudioSwitcherFilter), pGB))
5248 REFERENCE_TIME rtShift = pASF->GetAudioTimeShift();
5249 rtShift +=
5250 nID == ID_PLAY_INCAUDDELAY ? 100000 :
5251 nID == ID_PLAY_DECAUDDELAY ? -100000 :
5253 pASF->SetAudioTimeShift(rtShift);
5255 CString str;
5256 str.Format(_T("Audio Delay: %I64dms"), rtShift/10000);
5257 SendStatusMessage(str, 3000);
5261 void CMainFrame::OnUpdatePlayChangeAudDelay(CCmdUI* pCmdUI)
5263 pCmdUI->Enable(!!pGB /*&& !!FindFilter(__uuidof(CAudioSwitcherFilter), pGB)*/);
5266 #include "ComPropertySheet.h"
5268 void CMainFrame::OnPlayFilters(UINT nID)
5270 // ShowPPage(m_spparray[nID - ID_FILTERS_SUBITEM_START], m_hWnd);
5272 CComPtr<IUnknown> pUnk = m_pparray[nID - ID_FILTERS_SUBITEM_START];
5274 CComPropertySheet ps(ResStr(IDS_PROPSHEET_PROPERTIES), this);
5276 if(CComQIPtr<ISpecifyPropertyPages> pSPP = pUnk)
5278 ps.AddPages(pSPP);
5281 if(CComQIPtr<IBaseFilter> pBF = pUnk)
5283 HRESULT hr;
5284 CComPtr<IPropertyPage> pPP = new CInternalPropertyPageTempl<CPinInfoWnd>(NULL, &hr);
5285 ps.AddPage(pPP, pBF);
5288 if(ps.GetPageCount() > 0)
5290 ps.DoModal();
5291 OpenSetupStatusBar();
5295 void CMainFrame::OnUpdatePlayFilters(CCmdUI* pCmdUI)
5297 pCmdUI->Enable(!m_fCapturing);
5300 void CMainFrame::OnPlayShaders(UINT nID)
5302 if(nID == ID_SHADERS_START+2)
5304 ShowControlBar(&m_wndShaderEditorBar, TRUE, TRUE);
5305 return;
5308 if(!m_pCAP) return;
5310 if(nID == ID_SHADERS_START)
5312 m_shaderlabels.RemoveAll();
5314 else if(nID == ID_SHADERS_START+1)
5316 if(IDOK != CShaderCombineDlg(m_shaderlabels, this).DoModal())
5317 return;
5319 else if(nID >= ID_SHADERS_START+3)
5321 MENUITEMINFO mii;
5322 memset(&mii, 0, sizeof(mii));
5323 mii.cbSize = sizeof(mii);
5324 mii.fMask = MIIM_DATA;
5325 m_shaders.GetMenuItemInfo(nID, &mii);
5327 m_shaderlabels.RemoveAll();
5328 m_shaderlabels.AddTail(((const AppSettings::Shader*)mii.dwItemData)->label);
5331 SetShaders();
5334 void CMainFrame::OnUpdatePlayShaders(CCmdUI* pCmdUI)
5336 if(pCmdUI->m_nID >= ID_SHADERS_START)
5338 pCmdUI->Enable(!!m_pCAP);
5340 if(pCmdUI->m_nID == ID_SHADERS_START)
5342 pCmdUI->SetRadio(m_shaderlabels.IsEmpty());
5344 else if(pCmdUI->m_nID == ID_SHADERS_START+1)
5346 pCmdUI->SetRadio(m_shaderlabels.GetCount() > 1);
5348 else if(pCmdUI->m_nID == ID_SHADERS_START+2)
5350 pCmdUI->Enable(TRUE);
5352 else
5354 MENUITEMINFO mii;
5355 memset(&mii, 0, sizeof(mii));
5356 mii.cbSize = sizeof(mii);
5357 mii.fMask = MIIM_DATA;
5358 m_shaders.GetMenuItemInfo(pCmdUI->m_nID, &mii);
5360 pCmdUI->SetRadio(m_shaderlabels.GetCount() == 1
5361 && m_shaderlabels.GetHead() == ((AppSettings::Shader*)mii.dwItemData)->label);
5366 void CMainFrame::OnPlayAudio(UINT nID)
5368 int i = (int)nID - (1 + ID_AUDIO_SUBITEM_START);
5370 CComQIPtr<IAMStreamSelect> pSS = FindFilter(__uuidof(CAudioSwitcherFilter), pGB);
5371 if(!pSS) pSS = FindFilter(L"{D3CD7858-971A-4838-ACEC-40CA5D529DC8}", pGB);
5373 if(i == -1)
5375 ShowOptions(CPPageAudioSwitcher::IDD);
5377 else if(i >= 0 && pSS)
5379 pSS->Enable(i, AMSTREAMSELECTENABLE_ENABLE);
5383 void CMainFrame::OnUpdatePlayAudio(CCmdUI* pCmdUI)
5385 UINT nID = pCmdUI->m_nID;
5386 int i = (int)nID - (1 + ID_AUDIO_SUBITEM_START);
5388 CComQIPtr<IAMStreamSelect> pSS = FindFilter(__uuidof(CAudioSwitcherFilter), pGB);
5389 if(!pSS) pSS = FindFilter(L"{D3CD7858-971A-4838-ACEC-40CA5D529DC8}", pGB);
5391 /*if(i == -1)
5393 // TODO****
5395 else*/ if(i >= 0 && pSS)
5397 DWORD flags = 0;
5399 if(SUCCEEDED(pSS->Info(i, NULL, &flags, NULL, NULL, NULL, NULL, NULL)))
5401 if(flags&AMSTREAMSELECTINFO_EXCLUSIVE) pCmdUI->SetRadio(TRUE);
5402 else if(flags&AMSTREAMSELECTINFO_ENABLED) pCmdUI->SetCheck(TRUE);
5403 else pCmdUI->SetCheck(FALSE);
5405 else
5407 pCmdUI->Enable(FALSE);
5412 void CMainFrame::OnPlaySubtitles(UINT nID)
5414 int i = (int)nID - (4 + ID_SUBTITLES_SUBITEM_START);
5416 if(i == -4)
5418 ShowOptions(CPPageSubtitles::IDD);
5420 else if(i == -3)
5422 int i = m_iSubtitleSel;
5424 POSITION pos = m_pSubStreams.GetHeadPosition();
5425 while(pos && i >= 0)
5427 CComPtr<ISubStream> pSubStream = m_pSubStreams.GetNext(pos);
5429 if(i < pSubStream->GetStreamCount())
5431 CLSID clsid;
5432 if(FAILED(pSubStream->GetClassID(&clsid)))
5433 continue;
5435 if(clsid == __uuidof(CRenderedTextSubtitle))
5437 CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)pSubStream;
5439 CAutoPtrArray<CPPageSubStyle> pages;
5440 CAtlArray<STSStyle*> styles;
5442 POSITION pos = pRTS->m_styles.GetStartPosition();
5443 for(int i = 0; pos; i++)
5445 CString key;
5446 STSStyle* val;
5447 pRTS->m_styles.GetNextAssoc(pos, key, val);
5449 CAutoPtr<CPPageSubStyle> page(new CPPageSubStyle());
5450 page->InitStyle(key, *val);
5451 pages.Add(page);
5452 styles.Add(val);
5455 CPropertySheet dlg(_T("Styles..."), this);
5456 for(int i = 0; i < (int)pages.GetCount(); i++)
5457 dlg.AddPage(pages[i]);
5459 if(dlg.DoModal() == IDOK)
5461 for(int j = 0; j < (int)pages.GetCount(); j++)
5462 pages[j]->GetStyle(*styles[j]);
5463 UpdateSubtitle(false);
5466 return;
5470 i -= pSubStream->GetStreamCount();
5473 else if(i == -2)
5475 ReloadSubtitle();
5477 else if(i == -1)
5479 if(m_iSubtitleSel == -1) m_iSubtitleSel = 0;
5480 else m_iSubtitleSel ^= (1<<31);
5481 UpdateSubtitle();
5483 else if(i >= 0)
5485 m_iSubtitleSel = i;
5486 UpdateSubtitle();
5489 AfxGetAppSettings().fEnableSubtitles = !(m_iSubtitleSel & 0x80000000);
5492 void CMainFrame::OnUpdatePlaySubtitles(CCmdUI* pCmdUI)
5494 UINT nID = pCmdUI->m_nID;
5495 int i = (int)nID - (4 + ID_SUBTITLES_SUBITEM_START);
5497 pCmdUI->Enable(m_pCAP && !m_fAudioOnly);
5499 if(i == -3)
5501 pCmdUI->Enable(FALSE);
5503 int i = m_iSubtitleSel;
5505 POSITION pos = m_pSubStreams.GetHeadPosition();
5506 while(pos && i >= 0)
5508 CComPtr<ISubStream> pSubStream = m_pSubStreams.GetNext(pos);
5510 if(i < pSubStream->GetStreamCount())
5512 CLSID clsid;
5513 if(FAILED(pSubStream->GetClassID(&clsid)))
5514 continue;
5516 if(clsid == __uuidof(CRenderedTextSubtitle))
5518 pCmdUI->Enable(TRUE);
5519 break;
5523 i -= pSubStream->GetStreamCount();
5526 else if(i == -1)
5528 pCmdUI->SetCheck(m_iSubtitleSel >= 0);
5530 else if(i >= 0)
5532 pCmdUI->SetRadio(i == abs(m_iSubtitleSel));
5536 void CMainFrame::OnPlayLanguage(UINT nID)
5538 nID -= ID_FILTERSTREAMS_SUBITEM_START;
5539 CComPtr<IAMStreamSelect> pAMSS = m_ssarray[nID];
5540 UINT i = nID;
5541 while(i > 0 && pAMSS == m_ssarray[i-1]) i--;
5542 if(FAILED(pAMSS->Enable(nID-i, AMSTREAMSELECTENABLE_ENABLE)))
5543 MessageBeep(-1);
5545 OpenSetupStatusBar();
5548 void CMainFrame::OnUpdatePlayLanguage(CCmdUI* pCmdUI)
5550 UINT nID = pCmdUI->m_nID;
5551 nID -= ID_FILTERSTREAMS_SUBITEM_START;
5552 CComPtr<IAMStreamSelect> pAMSS = m_ssarray[nID];
5553 UINT i = nID;
5554 while(i > 0 && pAMSS == m_ssarray[i-1]) i--;
5555 DWORD flags = 0;
5556 pAMSS->Info(nID-i, NULL, &flags, NULL, NULL, NULL, NULL, NULL);
5557 if(flags&AMSTREAMSELECTINFO_EXCLUSIVE) pCmdUI->SetRadio(TRUE);
5558 else if(flags&AMSTREAMSELECTINFO_ENABLED) pCmdUI->SetCheck(TRUE);
5559 else pCmdUI->SetCheck(FALSE);
5562 void CMainFrame::OnPlayVolume(UINT nID)
5564 if(m_iMediaLoadState == MLS_LOADED)
5566 pBA->put_Volume(m_wndToolBar.Volume);
5570 void CMainFrame::OnPlayVolumeBoost(UINT nID)
5572 AppSettings& s = AfxGetAppSettings();
5574 int i = (int)(50.0f*log10(s.AudioBoost));
5576 switch(nID)
5578 case ID_VOLUME_BOOST_INC: i = min(i+10, 100); break;
5579 case ID_VOLUME_BOOST_DEC: i = max(i-10, 0); break;
5580 case ID_VOLUME_BOOST_MIN: i = 0; break;
5581 case ID_VOLUME_BOOST_MAX: i = 100; break;
5584 s.AudioBoost = pow(10.0f, (float)i/50);
5586 if(CComQIPtr<IAudioSwitcherFilter> pASF = FindFilter(__uuidof(CAudioSwitcherFilter), pGB))
5588 bool fNormalize, fNormalizeRecover;
5589 float boost;
5590 pASF->GetNormalizeBoost(fNormalize, fNormalizeRecover, boost);
5591 pASF->SetNormalizeBoost(fNormalize, fNormalizeRecover, s.AudioBoost);
5595 void CMainFrame::OnUpdatePlayVolumeBoost(CCmdUI* pCmdUI)
5597 pCmdUI->Enable();
5600 void CMainFrame::OnAfterplayback(UINT nID)
5602 AppSettings& s = AfxGetAppSettings();
5604 s.nCLSwitches &= ~CLSW_AFTERPLAYBACK_MASK;
5606 switch(nID)
5608 case ID_AFTERPLAYBACK_CLOSE: s.nCLSwitches |= CLSW_CLOSE; break;
5609 case ID_AFTERPLAYBACK_STANDBY: s.nCLSwitches |= CLSW_STANDBY; break;
5610 case ID_AFTERPLAYBACK_HIBERNATE: s.nCLSwitches |= CLSW_HIBERNATE; break;
5611 case ID_AFTERPLAYBACK_SHUTDOWN: s.nCLSwitches |= CLSW_SHUTDOWN; break;
5612 case ID_AFTERPLAYBACK_LOGOFF: s.nCLSwitches |= CLSW_LOGOFF; break;
5616 void CMainFrame::OnUpdateAfterplayback(CCmdUI* pCmdUI)
5618 AppSettings& s = AfxGetAppSettings();
5620 bool fChecked = false;
5622 switch(pCmdUI->m_nID)
5624 case ID_AFTERPLAYBACK_CLOSE: fChecked = !!(s.nCLSwitches & CLSW_CLOSE); break;
5625 case ID_AFTERPLAYBACK_STANDBY: fChecked = !!(s.nCLSwitches & CLSW_STANDBY); break;
5626 case ID_AFTERPLAYBACK_HIBERNATE: fChecked = !!(s.nCLSwitches & CLSW_HIBERNATE); break;
5627 case ID_AFTERPLAYBACK_SHUTDOWN: fChecked = !!(s.nCLSwitches & CLSW_SHUTDOWN); break;
5628 case ID_AFTERPLAYBACK_LOGOFF: fChecked = !!(s.nCLSwitches & CLSW_LOGOFF); break;
5629 case ID_AFTERPLAYBACK_DONOTHING: fChecked = !(s.nCLSwitches & CLSW_AFTERPLAYBACK_MASK); break;
5632 pCmdUI->SetRadio(fChecked);
5635 // navigate
5637 void CMainFrame::OnNavigateSkip(UINT nID)
5639 if(m_iPlaybackMode == PM_FILE || m_iPlaybackMode == PM_CAPTURE)
5641 if(m_iPlaybackMode == PM_FILE) SetupChapters();
5643 if(DWORD nChapters = m_pCB->ChapGetCount())
5645 REFERENCE_TIME rtCur;
5646 pMS->GetCurrentPosition(&rtCur);
5648 REFERENCE_TIME rt = rtCur;
5649 CComBSTR name;
5650 long i;
5652 if(nID == ID_NAVIGATE_SKIPBACK)
5654 rt -= 30000000;
5655 i = m_pCB->ChapLookup(&rt, &name);
5657 else if(nID == ID_NAVIGATE_SKIPFORWARD)
5659 i = m_pCB->ChapLookup(&rt, &name) + 1;
5660 name.Empty();
5661 if(i < nChapters) m_pCB->ChapGet(i, &rt, &name);
5664 if(i >= 0 && i < nChapters)
5666 SeekTo(rt);
5667 SendStatusMessage(_T("Chapter: ") + CString(name), 3000);
5668 return;
5672 if(nID == ID_NAVIGATE_SKIPBACK)
5674 SendMessage(WM_COMMAND, ID_NAVIGATE_SKIPBACKPLITEM);
5676 else if(nID == ID_NAVIGATE_SKIPFORWARD)
5678 SendMessage(WM_COMMAND, ID_NAVIGATE_SKIPFORWARDPLITEM);
5681 else if(m_iPlaybackMode == PM_DVD)
5683 m_iSpeedLevel = 0;
5685 if(GetMediaState() != State_Running)
5686 SendMessage(WM_COMMAND, ID_PLAY_PLAY);
5688 ULONG ulNumOfVolumes, ulVolume;
5689 DVD_DISC_SIDE Side;
5690 ULONG ulNumOfTitles = 0;
5691 pDVDI->GetDVDVolumeInfo(&ulNumOfVolumes, &ulVolume, &Side, &ulNumOfTitles);
5693 DVD_PLAYBACK_LOCATION2 Location;
5694 pDVDI->GetCurrentLocation(&Location);
5696 ULONG ulNumOfChapters = 0;
5697 pDVDI->GetNumberOfChapters(Location.TitleNum, &ulNumOfChapters);
5699 if(nID == ID_NAVIGATE_SKIPBACK)
5701 if(Location.ChapterNum == 1 && Location.TitleNum > 1)
5703 pDVDI->GetNumberOfChapters(Location.TitleNum-1, &ulNumOfChapters);
5704 pDVDC->PlayChapterInTitle(Location.TitleNum-1, ulNumOfChapters, DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
5706 else
5708 pDVDC->PlayPrevChapter(DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
5711 else if(nID == ID_NAVIGATE_SKIPFORWARD)
5713 if(Location.ChapterNum == ulNumOfChapters && Location.TitleNum < ulNumOfTitles)
5715 pDVDC->PlayChapterInTitle(Location.TitleNum+1, 1, DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
5717 else
5719 pDVDC->PlayNextChapter(DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
5723 if(nID == ID_NAVIGATE_SKIPBACK)
5724 pDVDC->PlayPrevChapter(DVD_CMD_FLAG_Block, NULL);
5725 else if(nID == ID_NAVIGATE_SKIPFORWARD)
5726 pDVDC->PlayNextChapter(DVD_CMD_FLAG_Block, NULL);
5731 void CMainFrame::OnUpdateNavigateSkip(CCmdUI* pCmdUI)
5733 // moved to the timer callback function, that runs less frequent
5734 // if(m_iPlaybackMode == PM_FILE) SetupChapters();
5736 pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED
5737 && ((m_iPlaybackMode == PM_DVD
5738 && m_iDVDDomain != DVD_DOMAIN_VideoManagerMenu
5739 && m_iDVDDomain != DVD_DOMAIN_VideoTitleSetMenu)
5740 || (m_iPlaybackMode == PM_FILE && (m_wndPlaylistBar.GetCount() > 1/*0*/ || m_pCB->ChapGetCount() > 1))
5741 || (m_iPlaybackMode == PM_CAPTURE && !m_fCapturing))); // TODO
5744 void CMainFrame::OnNavigateSkipPlaylistItem(UINT nID)
5746 if(m_iPlaybackMode == PM_FILE || m_iPlaybackMode == PM_CAPTURE)
5748 if(m_wndPlaylistBar.GetCount() == 1)
5750 SendMessage(WM_COMMAND, ID_PLAY_STOP); // do not remove this, unless you want a circular call with OnPlayPlay()
5751 SendMessage(WM_COMMAND, ID_PLAY_PLAY);
5753 else
5755 if(nID == ID_NAVIGATE_SKIPBACKPLITEM)
5757 m_wndPlaylistBar.SetPrev();
5759 else if(nID == ID_NAVIGATE_SKIPFORWARDPLITEM)
5761 m_wndPlaylistBar.SetNext();
5764 OpenCurPlaylistItem();
5769 void CMainFrame::OnUpdateNavigateSkipPlaylistItem(CCmdUI* pCmdUI)
5771 pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED
5772 && ((m_iPlaybackMode == PM_FILE || m_iPlaybackMode == PM_CAPTURE && !m_fCapturing) && m_wndPlaylistBar.GetCount() > 1/*0*/));
5775 void CMainFrame::OnNavigateMenu(UINT nID)
5777 nID -= ID_NAVIGATE_TITLEMENU;
5779 if(m_iMediaLoadState != MLS_LOADED || m_iPlaybackMode != PM_DVD)
5780 return;
5782 m_iSpeedLevel = 0;
5784 if(GetMediaState() != State_Running)
5785 SendMessage(WM_COMMAND, ID_PLAY_PLAY);
5787 pDVDC->ShowMenu((DVD_MENU_ID)(nID+2), DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
5790 void CMainFrame::OnUpdateNavigateMenu(CCmdUI* pCmdUI)
5792 UINT nID = pCmdUI->m_nID - ID_NAVIGATE_TITLEMENU;
5793 ULONG ulUOPs;
5795 if(m_iMediaLoadState != MLS_LOADED || m_iPlaybackMode != PM_DVD
5796 || FAILED(pDVDI->GetCurrentUOPS(&ulUOPs)))
5798 pCmdUI->Enable(FALSE);
5799 return;
5802 pCmdUI->Enable(!(ulUOPs & (UOP_FLAG_ShowMenu_Title << nID)));
5805 void CMainFrame::OnNavigateAudio(UINT nID)
5807 nID -= ID_NAVIGATE_AUDIO_SUBITEM_START;
5809 if(m_iPlaybackMode == PM_FILE)
5811 OnNavStreamSelectSubMenu(nID, 1);
5813 else if(m_iPlaybackMode == PM_DVD)
5815 pDVDC->SelectAudioStream(nID, DVD_CMD_FLAG_Block, NULL);
5819 void CMainFrame::OnNavigateSubpic(UINT nID)
5821 if(m_iPlaybackMode == PM_FILE)
5823 OnNavStreamSelectSubMenu(nID - ID_NAVIGATE_SUBP_SUBITEM_START, 2);
5825 else if(m_iPlaybackMode == PM_DVD)
5827 int i = (int)nID - (1 + ID_NAVIGATE_SUBP_SUBITEM_START);
5829 if(i == -1)
5831 ULONG ulStreamsAvailable, ulCurrentStream;
5832 BOOL bIsDisabled;
5833 if(SUCCEEDED(pDVDI->GetCurrentSubpicture(&ulStreamsAvailable, &ulCurrentStream, &bIsDisabled)))
5834 pDVDC->SetSubpictureState(bIsDisabled, DVD_CMD_FLAG_Block, NULL);
5836 else
5838 pDVDC->SelectSubpictureStream(i, DVD_CMD_FLAG_Block, NULL);
5839 pDVDC->SetSubpictureState(TRUE, DVD_CMD_FLAG_Block, NULL);
5844 void CMainFrame::OnNavigateAngle(UINT nID)
5846 nID -= ID_NAVIGATE_ANGLE_SUBITEM_START;
5848 if(m_iPlaybackMode == PM_FILE)
5850 OnNavStreamSelectSubMenu(nID, 0);
5852 else if(m_iPlaybackMode == PM_DVD)
5854 pDVDC->SelectAngle(nID+1, DVD_CMD_FLAG_Block, NULL);
5858 void CMainFrame::OnNavigateChapters(UINT nID)
5860 nID -= ID_NAVIGATE_CHAP_SUBITEM_START;
5862 if(m_iPlaybackMode == PM_FILE)
5864 if((int)nID >= 0 && nID < m_pCB->ChapGetCount())
5866 REFERENCE_TIME rt;
5867 CComBSTR name;
5868 if(SUCCEEDED(m_pCB->ChapGet(nID, &rt, &name)))
5870 SeekTo(rt);
5871 SendStatusMessage(_T("Chapter: ") + CString(name), 3000);
5873 return;
5876 nID -= m_pCB->ChapGetCount();
5878 if((int)nID >= 0 && (int)nID < m_wndPlaylistBar.GetCount()
5879 && m_wndPlaylistBar.GetSelIdx() != (int)nID)
5881 m_wndPlaylistBar.SetSelIdx(nID);
5882 OpenCurPlaylistItem();
5885 else if(m_iPlaybackMode == PM_DVD)
5887 ULONG ulNumOfVolumes, ulVolume;
5888 DVD_DISC_SIDE Side;
5889 ULONG ulNumOfTitles = 0;
5890 pDVDI->GetDVDVolumeInfo(&ulNumOfVolumes, &ulVolume, &Side, &ulNumOfTitles);
5892 DVD_PLAYBACK_LOCATION2 Location;
5893 pDVDI->GetCurrentLocation(&Location);
5895 ULONG ulNumOfChapters = 0;
5896 pDVDI->GetNumberOfChapters(Location.TitleNum, &ulNumOfChapters);
5898 nID++;
5900 if(nID > 0 && nID <= ulNumOfTitles)
5902 pDVDC->PlayTitle(nID, DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL); // sometimes this does not do anything ...
5903 pDVDC->PlayChapterInTitle(nID, 1, DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL); // ... but this does!
5904 return;
5907 nID -= ulNumOfTitles;
5909 if(nID > 0 && nID <= ulNumOfChapters)
5911 pDVDC->PlayChapter(nID, DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
5912 return;
5917 void CMainFrame::OnNavigateMenuItem(UINT nID)
5919 nID -= ID_NAVIGATE_MENU_LEFT;
5921 if(m_iPlaybackMode == PM_DVD)
5923 switch(nID)
5925 case 0: pDVDC->SelectRelativeButton(DVD_Relative_Left); break;
5926 case 1: pDVDC->SelectRelativeButton(DVD_Relative_Right); break;
5927 case 2: pDVDC->SelectRelativeButton(DVD_Relative_Upper); break;
5928 case 3: pDVDC->SelectRelativeButton(DVD_Relative_Lower); break;
5929 case 4: pDVDC->ActivateButton(); break;
5930 case 5: pDVDC->ReturnFromSubmenu(DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL); break;
5931 case 6: pDVDC->Resume(DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL); break;
5932 default: break;
5937 void CMainFrame::OnUpdateNavigateMenuItem(CCmdUI* pCmdUI)
5939 UINT nID = pCmdUI->m_nID - ID_NAVIGATE_MENU_LEFT;
5940 pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && m_iPlaybackMode == PM_DVD);
5943 // favorites
5945 class CDVDStateStream : public CUnknown, public IStream
5947 STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv)
5949 return
5950 QI(IStream)
5951 CUnknown::NonDelegatingQueryInterface(riid, ppv);
5954 __int64 m_pos;
5956 public:
5957 CDVDStateStream() : CUnknown(NAME("CDVDStateStream"), NULL) {m_pos = 0;}
5959 DECLARE_IUNKNOWN;
5961 CAtlArray<BYTE> m_data;
5963 // ISequentialStream
5964 STDMETHODIMP Read(void* pv, ULONG cb, ULONG* pcbRead)
5966 __int64 cbRead = min(m_data.GetCount() - m_pos, (__int64)cb);
5967 cbRead = max(cbRead, 0);
5968 memcpy(pv, &m_data[(INT_PTR)m_pos], (int)cbRead);
5969 if(pcbRead) *pcbRead = (ULONG)cbRead;
5970 m_pos += cbRead;
5971 return S_OK;
5973 STDMETHODIMP Write(const void* pv, ULONG cb, ULONG* pcbWritten)
5975 BYTE* p = (BYTE*)pv;
5976 ULONG cbWritten = -1;
5977 while(++cbWritten < cb)
5978 m_data.Add(*p++);
5979 if(pcbWritten) *pcbWritten = cbWritten;
5980 return S_OK;
5983 // IStream
5984 STDMETHODIMP Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition) {return E_NOTIMPL;}
5985 STDMETHODIMP SetSize(ULARGE_INTEGER libNewSize) {return E_NOTIMPL;}
5986 STDMETHODIMP CopyTo(IStream* pstm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten) {return E_NOTIMPL;}
5987 STDMETHODIMP Commit(DWORD grfCommitFlags) {return E_NOTIMPL;}
5988 STDMETHODIMP Revert() {return E_NOTIMPL;}
5989 STDMETHODIMP LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {return E_NOTIMPL;}
5990 STDMETHODIMP UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {return E_NOTIMPL;}
5991 STDMETHODIMP Stat(STATSTG* pstatstg, DWORD grfStatFlag) {return E_NOTIMPL;}
5992 STDMETHODIMP Clone(IStream** ppstm) {return E_NOTIMPL;}
5996 void CMainFrame::OnFavoritesAdd()
5998 AppSettings& s = AfxGetAppSettings();
6000 if(m_iPlaybackMode == PM_FILE)
6002 CString fn = m_wndPlaylistBar.GetCur();
6003 if(fn.IsEmpty()) return;
6005 CString desc = fn;
6006 desc.Replace('\\', '/');
6007 int i = desc.Find(_T("://")), j = desc.Find(_T("?")), k = desc.ReverseFind('/');
6008 if(i >= 0) desc = j >= 0 ? desc.Left(j) : desc;
6009 else if(k >= 0) desc = desc.Mid(k+1);
6011 CFavoriteAddDlg dlg(desc, fn);
6012 if(dlg.DoModal() != IDOK) return;
6014 CString str = dlg.m_name;
6015 str.Remove(';');
6017 CString pos(_T("0"));
6018 if(dlg.m_fRememberPos)
6019 pos.Format(_T("%I64d"), GetPos());
6021 str += ';';
6022 str += pos;
6024 CPlaylistItem pli;
6025 if(m_wndPlaylistBar.GetCur(pli))
6027 POSITION pos = pli.m_fns.GetHeadPosition();
6028 while(pos) str += _T(";") + pli.m_fns.GetNext(pos);
6031 s.AddFav(FAV_FILE, str);
6033 else if(m_iPlaybackMode == PM_DVD)
6035 WCHAR path[MAX_PATH];
6036 ULONG len = 0;
6037 pDVDI->GetDVDDirectory(path, MAX_PATH, &len);
6038 CString fn = path;
6039 fn.TrimRight(_T("/\\"));
6041 DVD_PLAYBACK_LOCATION2 Location;
6042 pDVDI->GetCurrentLocation(&Location);
6043 CString desc;
6044 desc.Format(_T("%s - T%02d C%02d - %02d:%02d:%02d"), fn, Location.TitleNum, Location.ChapterNum,
6045 Location.TimeCode.bHours, Location.TimeCode.bMinutes, Location.TimeCode.bSeconds);
6047 CFavoriteAddDlg dlg(fn, desc);
6048 if(dlg.DoModal() != IDOK) return;
6050 CString str = dlg.m_name;
6051 str.Remove(';');
6053 CString pos(_T("0"));
6054 if(dlg.m_fRememberPos)
6056 CDVDStateStream stream;
6057 stream.AddRef();
6059 CComPtr<IDvdState> pStateData;
6060 CComQIPtr<IPersistStream> pPersistStream;
6061 if(SUCCEEDED(pDVDI->GetState(&pStateData))
6062 && (pPersistStream = pStateData)
6063 && SUCCEEDED(OleSaveToStream(pPersistStream, (IStream*)&stream)))
6065 pos = BinToCString(stream.m_data.GetData(), stream.m_data.GetCount());
6069 str += ';';
6070 str += pos;
6072 str += ';';
6073 str += fn;
6075 s.AddFav(FAV_DVD, str);
6077 else if(m_iPlaybackMode == PM_CAPTURE)
6079 // TODO
6083 void CMainFrame::OnUpdateFavoritesAdd(CCmdUI* pCmdUI)
6085 pCmdUI->Enable(m_iPlaybackMode == PM_FILE || m_iPlaybackMode == PM_DVD);
6088 void CMainFrame::OnFavoritesOrganize()
6090 CFavoriteOrganizeDlg dlg;
6091 dlg.DoModal();
6094 void CMainFrame::OnUpdateFavoritesOrganize(CCmdUI* pCmdUI)
6096 // TODO: Add your command update UI handler code here
6099 void CMainFrame::OnFavoritesFile(UINT nID)
6101 nID -= ID_FAVORITES_FILE_START;
6103 CAtlList<CString> sl;
6104 AfxGetAppSettings().GetFav(FAV_FILE, sl);
6106 if(POSITION pos = sl.FindIndex(nID))
6108 CAtlList<CString> fns;
6109 REFERENCE_TIME rtStart = 0;
6111 int i = 0, j = 0;
6112 for(CString s1 = sl.GetAt(pos), s2 = s1.Tokenize(_T(";"), i);
6113 !s2.IsEmpty();
6114 s2 = s1.Tokenize(_T(";"), i), j++)
6116 if(j == 0) ; // desc
6117 else if(j == 1) _stscanf(s2, _T("%I64d"), &rtStart); // pos
6118 else fns.AddTail(s2); // subs
6121 m_wndPlaylistBar.Open(fns, false);
6122 OpenCurPlaylistItem(max(rtStart, 0));
6126 void CMainFrame::OnUpdateFavoritesFile(CCmdUI* pCmdUI)
6128 UINT nID = pCmdUI->m_nID - ID_FAVORITES_FILE_START;
6131 void CMainFrame::OnFavoritesDVD(UINT nID)
6133 nID -= ID_FAVORITES_DVD_START;
6135 CAtlList<CString> sl;
6136 AfxGetAppSettings().GetFav(FAV_DVD, sl);
6138 if(POSITION pos = sl.FindIndex(nID))
6140 CString fn;
6142 CDVDStateStream stream;
6143 stream.AddRef();
6145 int i = 0, j = 0;
6146 for(CString s1 = sl.GetAt(pos), s2 = s1.Tokenize(_T(";"), i);
6147 !s2.IsEmpty();
6148 s2 = s1.Tokenize(_T(";"), i), j++)
6150 if(j == 0) ; // desc
6151 else if(j == 1 && s2 != _T("0")) // state
6153 CStringToBin(s2, stream.m_data);
6155 else if(j == 2) fn = s2; // path
6158 SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
6160 CComPtr<IDvdState> pDvdState;
6161 HRESULT hr = OleLoadFromStream((IStream*)&stream, IID_IDvdState, (void**)&pDvdState);
6163 CAutoPtr<OpenDVDData> p(new OpenDVDData());
6164 if(p) {p->path = fn; p->pDvdState = pDvdState;}
6165 OpenMedia(p);
6169 void CMainFrame::OnUpdateFavoritesDVD(CCmdUI* pCmdUI)
6171 UINT nID = pCmdUI->m_nID - ID_FAVORITES_DVD_START;
6174 void CMainFrame::OnFavoritesDevice(UINT nID)
6176 nID -= ID_FAVORITES_DEVICE_START;
6179 void CMainFrame::OnUpdateFavoritesDevice(CCmdUI* pCmdUI)
6181 UINT nID = pCmdUI->m_nID - ID_FAVORITES_DEVICE_START;
6184 // help
6186 void CMainFrame::OnHelpHomepage()
6188 ShellExecute(m_hWnd, _T("open"), _T("http://sourceforge.net/projects/guliverkli2/"), NULL, NULL, SW_SHOWDEFAULT);
6191 void CMainFrame::OnHelpDocumentation()
6193 ShellExecute(m_hWnd, _T("open"), _T("http://sourceforge.net/project/showfiles.php?group_id=82303&package_id=144472"), NULL, NULL, SW_SHOWDEFAULT);
6196 //////////////////////////////////
6198 static BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
6200 CAtlArray<HMONITOR>* ml = (CAtlArray<HMONITOR>*)dwData;
6201 ml->Add(hMonitor);
6202 return TRUE;
6205 void CMainFrame::SetDefaultWindowRect(int iMonitor)
6207 AppSettings& s = AfxGetAppSettings();
6210 CRect r1, r2;
6211 GetClientRect(&r1);
6212 m_wndView.GetClientRect(&r2);
6214 CSize logosize = m_wndView.GetLogoSize();
6215 int _DEFCLIENTW = max(logosize.cx, DEFCLIENTW);
6216 int _DEFCLIENTH = max(logosize.cy, DEFCLIENTH);
6218 if(GetSystemMetrics(SM_REMOTESESSION))
6219 _DEFCLIENTH = 0;
6221 DWORD style = GetStyle();
6223 MENUBARINFO mbi;
6224 memset(&mbi, 0, sizeof(mbi));
6225 mbi.cbSize = sizeof(mbi);
6226 ::GetMenuBarInfo(m_hWnd, OBJID_MENU, 0, &mbi);
6228 int w = _DEFCLIENTW + GetSystemMetrics((style&WS_CAPTION)?SM_CXSIZEFRAME:SM_CXFIXEDFRAME)*2
6229 + r1.Width() - r2.Width();
6230 int h = _DEFCLIENTH + GetSystemMetrics((style&WS_CAPTION)?SM_CYSIZEFRAME:SM_CYFIXEDFRAME)*2
6231 + (mbi.rcBar.bottom - mbi.rcBar.top)
6232 + r1.Height() - r2.Height()
6233 + 1; // ???
6234 // + 2; // ???
6235 if(style&WS_CAPTION) h += GetSystemMetrics(SM_CYCAPTION);
6237 if(s.HasFixedWindowSize())
6239 w = s.fixedWindowSize.cx;
6240 h = s.fixedWindowSize.cy;
6242 else if(s.fRememberWindowSize)
6244 w = s.rcLastWindowPos.Width();
6245 h = s.rcLastWindowPos.Height();
6248 HMONITOR hMonitor = MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST);
6250 if(iMonitor > 0)
6252 iMonitor--;
6253 CAtlArray<HMONITOR> ml;
6254 EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM)&ml);
6255 if(iMonitor < ml.GetCount()) hMonitor = ml[iMonitor];
6258 MONITORINFO mi;
6259 mi.cbSize = sizeof(MONITORINFO);
6260 GetMonitorInfo(hMonitor, &mi);
6262 int x = (mi.rcWork.left+mi.rcWork.right-w)/2;
6263 int y = (mi.rcWork.top+mi.rcWork.bottom-h)/2;
6265 if(s.fRememberWindowPos)
6267 CRect r = s.rcLastWindowPos;
6268 // x = r.CenterPoint().x - w/2;
6269 // y = r.CenterPoint().y - h/2;
6270 x = r.TopLeft().x;
6271 y = r.TopLeft().y;
6274 UINT lastWindowType = s.lastWindowType;
6276 MoveWindow(x, y, w, h);
6278 if(s.fRememberWindowSize && s.fRememberWindowPos)
6280 WINDOWPLACEMENT wp;
6281 memset(&wp, 0, sizeof(wp));
6282 wp.length = sizeof(WINDOWPLACEMENT);
6283 if(lastWindowType == SIZE_MAXIMIZED)
6284 ShowWindow(SW_MAXIMIZE);
6285 else if(lastWindowType == SIZE_MINIMIZED)
6286 ShowWindow(SW_MINIMIZE);
6290 if(s.fHideCaptionMenu)
6292 ModifyStyle(WS_CAPTION, 0, SWP_NOZORDER);
6293 ::SetMenu(m_hWnd, NULL);
6294 SetWindowPos(NULL, 0, 0, 0, 0, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER);
6298 void CMainFrame::RestoreDefaultWindowRect()
6300 AppSettings& s = AfxGetAppSettings();
6302 WINDOWPLACEMENT wp;
6303 GetWindowPlacement(&wp);
6304 if(!m_fFullScreen && wp.showCmd != SW_SHOWMAXIMIZED && wp.showCmd != SW_SHOWMINIMIZED
6305 // && (GetExStyle()&WS_EX_APPWINDOW)
6306 && !s.fRememberWindowSize)
6308 CRect r1, r2;
6309 GetClientRect(&r1);
6310 m_wndView.GetClientRect(&r2);
6312 CSize logosize = m_wndView.GetLogoSize();
6313 int _DEFCLIENTW = max(logosize.cx, DEFCLIENTW);
6314 int _DEFCLIENTH = max(logosize.cy, DEFCLIENTH);
6316 DWORD style = GetStyle();
6318 MENUBARINFO mbi;
6319 memset(&mbi, 0, sizeof(mbi));
6320 mbi.cbSize = sizeof(mbi);
6321 ::GetMenuBarInfo(m_hWnd, OBJID_MENU, 0, &mbi);
6323 int w = _DEFCLIENTW + GetSystemMetrics((style&WS_CAPTION)?SM_CXSIZEFRAME:SM_CXFIXEDFRAME)*2
6324 + r1.Width() - r2.Width();
6325 int h = _DEFCLIENTH + GetSystemMetrics((style&WS_CAPTION)?SM_CYSIZEFRAME:SM_CYFIXEDFRAME)*2
6326 + (mbi.rcBar.bottom - mbi.rcBar.top)
6327 + r1.Height() - r2.Height()
6328 + 1; // ???
6329 // + 2; // ???
6330 if(style&WS_CAPTION) h += GetSystemMetrics(SM_CYCAPTION);
6332 if(s.HasFixedWindowSize())
6334 w = s.fixedWindowSize.cx;
6335 h = s.fixedWindowSize.cy;
6338 CRect r;
6339 GetWindowRect(r);
6341 int x = r.CenterPoint().x - w/2;
6342 int y = r.CenterPoint().y - h/2;
6344 if(s.fRememberWindowPos)
6346 CRect r = s.rcLastWindowPos;
6348 x = r.TopLeft().x;
6349 y = r.TopLeft().y;
6352 MoveWindow(x, y, w, h);
6356 OAFilterState CMainFrame::GetMediaState()
6358 OAFilterState ret = -1;
6359 if(m_iMediaLoadState == MLS_LOADED) pMC->GetState(0, &ret);
6360 return(ret);
6363 CSize CMainFrame::GetVideoSize()
6365 bool fKeepAspectRatio = AfxGetAppSettings().fKeepAspectRatio;
6366 bool fCompMonDeskARDiff = AfxGetAppSettings().fCompMonDeskARDiff;
6368 CSize ret(0,0);
6369 if(m_iMediaLoadState != MLS_LOADED || m_fAudioOnly)
6370 return ret;
6372 CSize wh(0, 0), arxy(0, 0);
6374 if(m_pCAP)
6376 wh = m_pCAP->GetVideoSize(false);
6377 arxy = m_pCAP->GetVideoSize(fKeepAspectRatio);
6379 else
6381 pBV->GetVideoSize(&wh.cx, &wh.cy);
6383 long arx = 0, ary = 0;
6384 CComQIPtr<IBasicVideo2> pBV2 = pBV;
6385 if(pBV2 && SUCCEEDED(pBV2->GetPreferredAspectRatio(&arx, &ary)) && arx > 0 && ary > 0)
6386 arxy.SetSize(arx, ary);
6389 if(wh.cx <= 0 || wh.cy <= 0)
6390 return ret;
6392 // with the overlay mixer IBasicVideo2 won't tell the new AR when changed dynamically
6393 DVD_VideoAttributes VATR;
6394 if(m_iPlaybackMode == PM_DVD && SUCCEEDED(pDVDI->GetCurrentVideoAttributes(&VATR)))
6395 arxy.SetSize(VATR.ulAspectX, VATR.ulAspectY);
6397 CSize& ar = AfxGetAppSettings().AspectRatio;
6398 if(ar.cx && ar.cy) arxy = ar;
6400 ret = (!fKeepAspectRatio || arxy.cx <= 0 || arxy.cy <= 0)
6401 ? wh
6402 : CSize(MulDiv(wh.cy, arxy.cx, arxy.cy), wh.cy);
6404 if(fCompMonDeskARDiff)
6405 if(HDC hDC = ::GetDC(0))
6407 int _HORZSIZE = GetDeviceCaps(hDC, HORZSIZE);
6408 int _VERTSIZE = GetDeviceCaps(hDC, VERTSIZE);
6409 int _HORZRES = GetDeviceCaps(hDC, HORZRES);
6410 int _VERTRES = GetDeviceCaps(hDC, VERTRES);
6412 if(_HORZSIZE > 0 && _VERTSIZE > 0 && _HORZRES > 0 && _VERTRES > 0)
6414 double a = 1.0*_HORZSIZE/_VERTSIZE;
6415 double b = 1.0*_HORZRES/_VERTRES;
6417 if(b < a)
6418 ret.cy = (DWORD)(1.0*ret.cy * a / b);
6419 else if(a < b)
6420 ret.cx = (DWORD)(1.0*ret.cx * b / a);
6423 ::ReleaseDC(0, hDC);
6426 return ret;
6429 void CMainFrame::ToggleFullscreen(bool fToNearest, bool fSwitchScreenResWhenHasTo)
6431 CRect r;
6432 // const CWnd* pWndInsertAfter;
6433 DWORD dwRemove = 0, dwAdd = 0;
6434 DWORD dwRemoveEx = 0, dwAddEx = 0;
6435 HMENU hMenu;
6437 if(!m_fFullScreen)
6439 GetWindowRect(&m_lastWindowRect);
6441 dispmode& dm = AfxGetAppSettings().dmFullscreenRes;
6442 m_dmBeforeFullscreen.fValid = false;
6443 if(dm.fValid && fSwitchScreenResWhenHasTo)
6445 GetCurDispMode(m_dmBeforeFullscreen);
6446 SetDispMode(dm);
6449 MONITORINFO mi;
6450 mi.cbSize = sizeof(MONITORINFO);
6451 GetMonitorInfo(MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST), &mi);
6453 dwRemove = WS_CAPTION|WS_THICKFRAME;
6454 if(fToNearest) r = mi.rcMonitor;
6455 else GetDesktopWindow()->GetWindowRect(&r);
6456 hMenu = NULL;
6458 else
6460 if(m_dmBeforeFullscreen.fValid)
6461 SetDispMode(m_dmBeforeFullscreen);
6463 dwAdd = (AfxGetAppSettings().fHideCaptionMenu ? 0 : WS_CAPTION) | WS_THICKFRAME;
6464 r = m_lastWindowRect;
6465 hMenu = AfxGetAppSettings().fHideCaptionMenu ? NULL : m_hMenuDefault;
6468 m_lastMouseMove.x = m_lastMouseMove.y = -1;
6470 bool fAudioOnly = m_fAudioOnly;
6471 m_fAudioOnly = true;
6473 m_fFullScreen = !m_fFullScreen;
6475 SetAlwaysOnTop(AfxGetAppSettings().iOnTop);
6477 ModifyStyle(dwRemove, dwAdd, SWP_NOZORDER);
6478 ModifyStyleEx(dwRemoveEx, dwAddEx, SWP_NOZORDER);
6479 ::SetMenu(m_hWnd, hMenu);
6480 SetWindowPos(NULL, r.left, r.top, r.Width(), r.Height(), SWP_NOZORDER|SWP_NOSENDCHANGING /*SWP_FRAMECHANGED*/);
6482 if(m_fFullScreen)
6484 m_fHideCursor = true;
6485 ShowControls(CS_NONE, false);
6487 else
6489 KillTimer(TIMER_FULLSCREENCONTROLBARHIDER);
6490 KillTimer(TIMER_FULLSCREENMOUSEHIDER);
6491 m_fHideCursor = false;
6492 ShowControls(AfxGetAppSettings().nCS);
6495 m_wndView.SetWindowPos(NULL, 0, 0, 0, 0, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER);
6497 m_fAudioOnly = fAudioOnly;
6499 MoveVideoWindow();
6502 void CMainFrame::MoveVideoWindow(bool fShowStats)
6504 if(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly && IsWindowVisible())
6506 CRect wr;
6507 if(!m_fFullScreen)
6509 m_wndView.GetClientRect(wr);
6510 if(!AfxGetAppSettings().fHideCaptionMenu)
6511 wr.DeflateRect(2, 2);
6513 else
6515 GetWindowRect(&wr);
6517 // HACK
6518 CRect r;
6519 m_wndView.GetWindowRect(&r);
6520 wr -= r.TopLeft();
6523 CRect vr = CRect(0,0,0,0);
6525 OAFilterState fs = GetMediaState();
6526 if(fs == State_Paused || fs == State_Running || fs == State_Stopped && (m_fShockwaveGraph || m_fQuicktimeGraph))
6528 CSize arxy = GetVideoSize();
6530 int iDefaultVideoSize = AfxGetAppSettings().iDefaultVideoSize;
6532 CSize ws =
6533 iDefaultVideoSize == DVS_HALF ? CSize(arxy.cx/2, arxy.cy/2) :
6534 iDefaultVideoSize == DVS_NORMAL ? arxy :
6535 iDefaultVideoSize == DVS_DOUBLE ? CSize(arxy.cx*2, arxy.cy*2) :
6536 wr.Size();
6538 int w = ws.cx;
6539 int h = ws.cy;
6541 if(!m_fShockwaveGraph) //&& !m_fQuicktimeGraph)
6543 if(iDefaultVideoSize == DVS_FROMINSIDE || iDefaultVideoSize == DVS_FROMOUTSIDE)
6545 h = ws.cy;
6546 w = MulDiv(h, arxy.cx, arxy.cy);
6548 if(iDefaultVideoSize == DVS_FROMINSIDE && w > ws.cx
6549 || iDefaultVideoSize == DVS_FROMOUTSIDE && w < ws.cx)
6551 w = ws.cx;
6552 h = MulDiv(w, arxy.cy, arxy.cx);
6557 CSize size(
6558 (int)(m_ZoomX*w),
6559 (int)(m_ZoomY*h));
6561 CPoint pos(
6562 (int)(m_PosX*(wr.Width()*3 - m_ZoomX*w) - wr.Width()),
6563 (int)(m_PosY*(wr.Height()*3 - m_ZoomY*h) - wr.Height()));
6565 /* CPoint pos(
6566 (int)(m_PosX*(wr.Width() - size.cx)),
6567 (int)(m_PosY*(wr.Height() - size.cy)));
6570 vr = CRect(pos, size);
6573 wr |= CRect(0,0,0,0);
6574 vr |= CRect(0,0,0,0);
6576 if(m_pCAP)
6578 m_pCAP->SetPosition(wr, vr);
6579 m_pCAP->SetVideoAngle(Vector(DegToRad(m_AngleX), DegToRad(m_AngleY), DegToRad(m_AngleZ)));
6581 else
6583 HRESULT hr;
6584 hr = pBV->SetDefaultSourcePosition();
6585 hr = pBV->SetDestinationPosition(vr.left, vr.top, vr.Width(), vr.Height());
6586 hr = pVW->SetWindowPosition(wr.left, wr.top, wr.Width(), wr.Height());
6589 m_wndView.SetVideoRect(wr);
6591 if(fShowStats && vr.Height() > 0)
6593 CString info;
6594 info.Format(_T("Pos %.2f %.2f, Zoom %.2f %.2f, AR %.2f"), m_PosX, m_PosY, m_ZoomX, m_ZoomY, (float)vr.Width()/vr.Height());
6595 SendStatusMessage(info, 3000);
6598 else
6600 m_wndView.SetVideoRect();
6604 void CMainFrame::ZoomVideoWindow(double scale)
6606 if(m_iMediaLoadState != MLS_LOADED)
6607 return;
6609 AppSettings& s = AfxGetAppSettings();
6611 if(scale <= 0)
6613 scale =
6614 s.iZoomLevel == 0 ? 0.5 :
6615 s.iZoomLevel == 1 ? 1.0 :
6616 s.iZoomLevel == 2 ? 2.0 :
6617 s.iZoomLevel == 3 ? GetZoomAutoFitScale() :
6618 1.0;
6621 if(m_fFullScreen)
6623 OnViewFullscreen();
6626 MINMAXINFO mmi;
6627 OnGetMinMaxInfo(&mmi);
6629 CRect r;
6630 int w = 0, h = 0;
6632 if(!m_fAudioOnly)
6634 CSize arxy = GetVideoSize();
6636 long lWidth = int(arxy.cx * scale + 0.5);
6637 long lHeight = int(arxy.cy * scale + 0.5);
6639 DWORD style = GetStyle();
6641 CRect r1, r2;
6642 GetClientRect(&r1);
6643 m_wndView.GetClientRect(&r2);
6645 w = GetSystemMetrics((style&WS_CAPTION)?SM_CXSIZEFRAME:SM_CXFIXEDFRAME)*2
6646 + r1.Width() - r2.Width()
6647 + lWidth;
6649 MENUBARINFO mbi;
6650 memset(&mbi, 0, sizeof(mbi));
6651 mbi.cbSize = sizeof(mbi);
6652 ::GetMenuBarInfo(m_hWnd, OBJID_MENU, 0, &mbi);
6654 h = GetSystemMetrics((style&WS_CAPTION)?SM_CYSIZEFRAME:SM_CYFIXEDFRAME)*2
6655 + (mbi.rcBar.bottom - mbi.rcBar.top)
6656 + r1.Height() - r2.Height()
6657 + lHeight;
6659 if(style&WS_CAPTION)
6661 h += GetSystemMetrics(SM_CYCAPTION);
6662 w += 2; h += 2; // for the 1 pixel wide sunken frame
6663 w += 2; h += 3; // for the inner black border
6666 GetWindowRect(r);
6668 w = max(w, mmi.ptMinTrackSize.x);
6669 h = max(h, mmi.ptMinTrackSize.y);
6671 else
6673 GetWindowRect(r);
6675 w = r.Width(); // mmi.ptMinTrackSize.x;
6676 h = mmi.ptMinTrackSize.y;
6679 // center window
6680 if(!s.fRememberWindowPos)
6682 CPoint cp = r.CenterPoint();
6683 r.left = cp.x - w/2;
6684 r.top = cp.y - h/2;
6687 r.right = r.left + w;
6688 r.bottom = r.top + h;
6690 MONITORINFO mi;
6691 mi.cbSize = sizeof(MONITORINFO);
6692 GetMonitorInfo(MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST), &mi);
6693 if(r.right > mi.rcWork.right) r.OffsetRect(mi.rcWork.right-r.right, 0);
6694 if(r.left < mi.rcWork.left) r.OffsetRect(mi.rcWork.left-r.left, 0);
6695 if(r.bottom > mi.rcWork.bottom) r.OffsetRect(0, mi.rcWork.bottom-r.bottom);
6696 if(r.top < mi.rcWork.top) r.OffsetRect(0, mi.rcWork.top-r.top);
6698 if(m_fFullScreen || !s.HasFixedWindowSize())
6700 MoveWindow(r);
6703 // ShowWindow(SW_SHOWNORMAL);
6705 MoveVideoWindow();
6708 double CMainFrame::GetZoomAutoFitScale()
6710 if(m_iMediaLoadState != MLS_LOADED || m_fAudioOnly)
6711 return 1.0;
6713 CSize arxy = GetVideoSize();
6715 double sx = 2.0/3 * m_rcDesktop.Width() / arxy.cx;
6716 double sy = 2.0/3 * m_rcDesktop.Height() / arxy.cy;
6718 return sx < sy ? sx : sy;
6721 void CMainFrame::RepaintVideo()
6723 if(m_pCAP) m_pCAP->Paint(false);
6726 void CMainFrame::SetShaders()
6728 if(!m_pCAP) return;
6730 AppSettings& s = AfxGetAppSettings();
6732 CAtlStringMap<const AppSettings::Shader*> s2s;
6734 POSITION pos = s.m_shaders.GetHeadPosition();
6735 while(pos)
6737 const AppSettings::Shader* pShader = &s.m_shaders.GetNext(pos);
6738 s2s[pShader->label] = pShader;
6741 m_pCAP->SetPixelShader(NULL, NULL);
6743 CAtlList<CString> labels;
6745 pos = m_shaderlabels.GetHeadPosition();
6746 while(pos)
6748 const AppSettings::Shader* pShader = NULL;
6749 if(s2s.Lookup(m_shaderlabels.GetNext(pos), pShader))
6751 CStringA target = pShader->target;
6752 CStringA srcdata = pShader->srcdata;
6754 HRESULT hr = m_pCAP->SetPixelShader(srcdata, target);
6756 if(FAILED(hr))
6758 m_pCAP->SetPixelShader(NULL, NULL);
6759 SendStatusMessage(_T("Could not load shader: ") + pShader->label, 3000);
6760 return;
6763 labels.AddTail(pShader->label);
6767 if(m_iMediaLoadState == MLS_LOADED)
6769 CString str = Implode(labels, '|');
6770 str.Replace(_T("|"), _T(", "));
6771 SendStatusMessage(_T("Shader: ") + str, 3000);
6775 void CMainFrame::UpdateShaders(CString label)
6777 if(!m_pCAP) return;
6779 if(m_shaderlabels.GetCount() <= 1)
6780 m_shaderlabels.RemoveAll();
6782 if(m_shaderlabels.IsEmpty() && !label.IsEmpty())
6783 m_shaderlabels.AddTail(label);
6785 bool fUpdate = m_shaderlabels.IsEmpty();
6787 POSITION pos = m_shaderlabels.GetHeadPosition();
6788 while(pos)
6790 if(label == m_shaderlabels.GetNext(pos))
6792 fUpdate = true;
6793 break;
6797 if(fUpdate) SetShaders();
6801 void CMainFrame::SetBalance(int balance)
6803 AfxGetAppSettings().nBalance = balance;
6805 int sign = balance>0?-1:1;
6806 balance = max(100-abs(balance), 1);
6807 balance = (int)((log10(1.0*balance)-2)*5000*sign);
6808 balance = max(min(balance, 10000), -10000);
6810 if(m_iMediaLoadState == MLS_LOADED)
6811 pBA->put_Balance(balance);
6814 void CMainFrame::SetupIViAudReg()
6816 if(!AfxGetAppSettings().fAutoSpeakerConf) return;
6818 DWORD spc = 0, defchnum = 0;
6820 if(AfxGetAppSettings().fAutoSpeakerConf)
6822 CComPtr<IDirectSound> pDS;
6823 if(SUCCEEDED(DirectSoundCreate(NULL, &pDS, NULL))
6824 && SUCCEEDED(pDS->SetCooperativeLevel(m_hWnd, DSSCL_NORMAL)))
6826 if(SUCCEEDED(pDS->GetSpeakerConfig(&spc)))
6828 switch(spc)
6830 case DSSPEAKER_DIRECTOUT: defchnum = 6; break;
6831 case DSSPEAKER_HEADPHONE: defchnum = 2; break;
6832 case DSSPEAKER_MONO: defchnum = 1; break;
6833 case DSSPEAKER_QUAD: defchnum = 4; break;
6834 default:
6835 case DSSPEAKER_STEREO: defchnum = 2; break;
6836 case DSSPEAKER_SURROUND: defchnum = 2; break;
6837 case DSSPEAKER_5POINT1: defchnum = 5; break;
6838 case DSSPEAKER_7POINT1: defchnum = 5; break;
6843 else
6845 defchnum = 2;
6848 CRegKey iviaud;
6849 if(ERROR_SUCCESS == iviaud.Create(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\InterVideo\\Common\\AudioDec")))
6851 DWORD chnum = 0;
6852 if(FAILED(iviaud.QueryDWORDValue(_T("AUDIO"), chnum))) chnum = 0;
6853 if(chnum <= defchnum) // check if the user has already set it..., but we won't skip if it's lower than sensible :P
6854 iviaud.SetDWORDValue(_T("AUDIO"), defchnum);
6859 // Open/Close
6863 void CMainFrame::OpenCreateGraphObject(OpenMediaData* pOMD)
6865 ASSERT(pGB == NULL);
6867 m_fCustomGraph = false;
6868 m_fRealMediaGraph = m_fShockwaveGraph = m_fQuicktimeGraph = false;
6870 AppSettings& s = AfxGetAppSettings();
6872 if(OpenFileData* p = dynamic_cast<OpenFileData*>(pOMD))
6874 engine_t engine = s.Formats.GetEngine(p->fns.GetHead());
6876 CStringA ct = GetContentType(p->fns.GetHead());
6878 if(ct == "video/x-ms-asf")
6880 // TODO: put something here to make the windows media source filter load later
6882 else if(ct == "audio/x-pn-realaudio"
6883 || ct == "audio/x-pn-realaudio-plugin"
6884 || ct == "audio/x-realaudio-secure"
6885 || ct == "video/vnd.rn-realvideo-secure"
6886 || ct == "application/vnd.rn-realmedia"
6887 || ct.Find("vnd.rn-") >= 0
6888 || ct.Find("realaudio") >= 0
6889 || ct.Find("realvideo") >= 0)
6891 engine = RealMedia;
6893 else if(ct == "application/x-shockwave-flash")
6895 engine = ShockWave;
6897 else if(ct == "video/quicktime"
6898 || ct == "application/x-quicktimeplayer")
6900 engine = QuickTime;
6903 HRESULT hr;
6904 CComPtr<IUnknown> pUnk;
6906 if(engine == RealMedia)
6908 if(!(pUnk = (IUnknown*)(INonDelegatingUnknown*)new CRealMediaGraph(m_wndView.m_hWnd, hr)))
6909 throw _T("Out of memory");
6911 if(SUCCEEDED(hr) && !!(pGB = CComQIPtr<IGraphBuilder>(pUnk)))
6912 m_fRealMediaGraph = true;
6914 else if(engine == ShockWave)
6916 if(!(pUnk = (IUnknown*)(INonDelegatingUnknown*)new CShockwaveGraph(m_wndView.m_hWnd, hr)))
6917 throw _T("Out of memory");
6919 if(FAILED(hr) || !(pGB = CComQIPtr<IGraphBuilder>(pUnk)))
6920 throw _T("Can't create shockwave control");
6922 m_fShockwaveGraph = true;
6924 else if(engine == QuickTime)
6926 if(!(pUnk = (IUnknown*)(INonDelegatingUnknown*)new CQuicktimeGraph(m_wndView.m_hWnd, hr)))
6927 throw _T("Out of memory");
6929 if(SUCCEEDED(hr) && !!(pGB = CComQIPtr<IGraphBuilder>(pUnk)))
6930 m_fQuicktimeGraph = true;
6933 m_fCustomGraph = m_fRealMediaGraph || m_fShockwaveGraph || m_fQuicktimeGraph;
6935 if(!m_fCustomGraph)
6937 pGB = new CFGManagerPlayer(_T("CFGManagerPlayer"), NULL, s.SrcFilters, s.TraFilters, m_wndView.m_hWnd);
6940 else if(OpenDVDData* p = dynamic_cast<OpenDVDData*>(pOMD))
6942 pGB = new CFGManagerDVD(_T("CFGManagerDVD"), NULL, s.SrcFilters, s.TraFilters, m_wndView.m_hWnd);
6944 else if(OpenDeviceData* p = dynamic_cast<OpenDeviceData*>(pOMD))
6946 pGB = new CFGManagerCapture(_T("CFGManagerCapture"), NULL, s.SrcFilters, s.TraFilters, m_wndView.m_hWnd);
6949 if(!pGB)
6951 throw _T("Failed to create the filter graph object");
6954 pGB->AddToROT();
6956 pMC = pGB; pME = pGB; pMS = pGB; // general
6957 pVW = pGB; pBV = pGB; // video
6958 pBA = pGB; // audio
6959 pFS = pGB;
6961 if(!(pMC && pME && pMS)
6962 || !(pVW && pBV)
6963 || !(pBA))
6965 throw _T("Failed to query the needed interfaces for playback");
6968 if(FAILED(pME->SetNotifyWindow((OAHWND)m_hWnd, WM_GRAPHNOTIFY, 0)))
6970 throw _T("Could not set target window for graph notification");
6973 m_pProv = (IUnknown*)new CKeyProvider();
6975 if(CComQIPtr<IObjectWithSite> pObjectWithSite = pGB)
6976 pObjectWithSite->SetSite(m_pProv);
6978 m_pCB = new CDSMChapterBag(NULL, NULL);
6981 void CMainFrame::OpenFile(OpenFileData* pOFD)
6983 if(pOFD->fns.IsEmpty())
6984 throw _T("Invalid argument");
6986 AppSettings& s = AfxGetAppSettings();
6988 bool fFirst = true;
6990 POSITION pos = pOFD->fns.GetHeadPosition();
6991 while(pos)
6993 CString fn = pOFD->fns.GetNext(pos);
6995 fn.Trim();
6996 if(fn.IsEmpty() && !fFirst)
6997 break;
6999 HRESULT hr = pGB->RenderFile(CStringW(fn), NULL);
7001 if(FAILED(hr))
7003 if(fFirst)
7005 if(s.fReportFailedPins)
7007 CComQIPtr<IGraphBuilderDeadEnd> pGBDE = pGB;
7008 if(pGBDE && pGBDE->GetCount()) CMediaTypesDlg(pGBDE, this).DoModal();
7011 CString err;
7013 switch(hr)
7015 case E_ABORT: err = _T("Opening aborted"); break;
7016 case E_FAIL: case E_POINTER: default: err = _T("Failed to render the file"); break;
7017 case E_INVALIDARG: err = _T("Invalid file name"); break;
7018 case E_OUTOFMEMORY: err = _T("Out of memory"); break;
7019 case VFW_E_CANNOT_CONNECT: err = _T("Cannot connect the filters"); break;
7020 case VFW_E_CANNOT_LOAD_SOURCE_FILTER: err = _T("Cannot load any source filter"); break;
7021 case VFW_E_CANNOT_RENDER: err = _T("Cannot render the file"); break;
7022 case VFW_E_INVALID_FILE_FORMAT: err = _T("Invalid file format"); break;
7023 case VFW_E_NOT_FOUND: err = _T("File not found"); break;
7024 case VFW_E_UNKNOWN_FILE_TYPE: err = _T("Unknown file type"); break;
7025 case VFW_E_UNSUPPORTED_STREAM: err = _T("Unsupported stream"); break;
7028 throw err;
7032 if(s.fKeepHistory)
7034 CRecentFileList* pMRU = fFirst ? &s.MRU : &s.MRUDub;
7035 pMRU->ReadList();
7036 pMRU->Add(fn);
7037 pMRU->WriteList();
7040 if(fFirst)
7042 pOFD->title = fn;
7045 fFirst = false;
7047 if(m_fCustomGraph) break;
7050 if(s.fReportFailedPins)
7052 CComQIPtr<IGraphBuilderDeadEnd> pGBDE = pGB;
7053 if(pGBDE && pGBDE->GetCount()) CMediaTypesDlg(pGBDE, this).DoModal();
7056 if(!(pAMOP = pGB))
7058 BeginEnumFilters(pGB, pEF, pBF)
7059 if(pAMOP = pBF) break;
7060 EndEnumFilters
7063 if(FindFilter(__uuidof(CShoutcastSource), pGB))
7064 m_fUpdateInfoBar = true;
7066 SetupChapters();
7068 CComQIPtr<IKeyFrameInfo> pKFI;
7069 BeginEnumFilters(pGB, pEF, pBF)
7070 if(pKFI = pBF) break;
7071 EndEnumFilters
7072 UINT nKFs = 0, nKFsTmp = 0;
7073 if(pKFI && S_OK == pKFI->GetKeyFrameCount(nKFs) && nKFs > 0)
7075 m_kfs.SetCount(nKFsTmp = nKFs);
7076 if(S_OK != pKFI->GetKeyFrames(&TIME_FORMAT_MEDIA_TIME, m_kfs.GetData(), nKFsTmp) || nKFsTmp != nKFs)
7077 m_kfs.RemoveAll();
7080 m_iPlaybackMode = PM_FILE;
7083 void CMainFrame::SetupChapters()
7085 ASSERT(m_pCB);
7087 m_pCB->ChapRemoveAll();
7089 CInterfaceList<IBaseFilter> pBFs;
7090 BeginEnumFilters(pGB, pEF, pBF)
7091 pBFs.AddTail(pBF);
7092 EndEnumFilters
7094 POSITION pos;
7096 pos = pBFs.GetHeadPosition();
7097 while(pos && !m_pCB->ChapGetCount())
7099 IBaseFilter* pBF = pBFs.GetNext(pos);
7101 CComQIPtr<IDSMChapterBag> pCB = pBF;
7102 if(!pCB) continue;
7104 for(DWORD i = 0, cnt = pCB->ChapGetCount(); i < cnt; i++)
7106 REFERENCE_TIME rt;
7107 CComBSTR name;
7108 if(SUCCEEDED(pCB->ChapGet(i, &rt, &name)))
7109 m_pCB->ChapAppend(rt, name);
7113 pos = pBFs.GetHeadPosition();
7114 while(pos && !m_pCB->ChapGetCount())
7116 IBaseFilter* pBF = pBFs.GetNext(pos);
7118 CComQIPtr<IChapterInfo> pCI = pBF;
7119 if(!pCI) continue;
7121 CHAR iso6391[3];
7122 ::GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SISO639LANGNAME, iso6391, 3);
7123 CStringA iso6392 = ISO6391To6392(iso6391);
7124 if(iso6392.GetLength() < 3) iso6392 = "eng";
7126 UINT cnt = pCI->GetChapterCount(CHAPTER_ROOT_ID);
7127 for(UINT i = 1; i <= cnt; i++)
7129 UINT cid = pCI->GetChapterId(CHAPTER_ROOT_ID, i);
7131 ChapterElement ce;
7132 if(pCI->GetChapterInfo(cid, &ce))
7134 char pl[3] = {iso6392[0], iso6392[1], iso6392[2]};
7135 char cc[] = " ";
7136 CComBSTR name;
7137 name.Attach(pCI->GetChapterStringInfo(cid, pl, cc));
7138 m_pCB->ChapAppend(ce.rtStart, name);
7143 pos = pBFs.GetHeadPosition();
7144 while(pos && !m_pCB->ChapGetCount())
7146 IBaseFilter* pBF = pBFs.GetNext(pos);
7148 CComQIPtr<IAMExtendedSeeking, &IID_IAMExtendedSeeking> pES = pBF;
7149 if(!pES) continue;
7151 long MarkerCount = 0;
7152 if(SUCCEEDED(pES->get_MarkerCount(&MarkerCount)))
7154 for(long i = 1; i <= MarkerCount; i++)
7156 double MarkerTime = 0;
7157 if(SUCCEEDED(pES->GetMarkerTime(i, &MarkerTime)))
7159 CStringW name;
7160 name.Format(L"Chapter %d", i);
7162 CComBSTR bstr;
7163 if(S_OK == pES->GetMarkerName(i, &bstr))
7164 name = bstr;
7166 m_pCB->ChapAppend(REFERENCE_TIME(MarkerTime*10000000), name);
7172 pos = pBFs.GetHeadPosition();
7173 while(pos && !m_pCB->ChapGetCount())
7175 IBaseFilter* pBF = pBFs.GetNext(pos);
7177 if(GetCLSID(pBF) != CLSID_OggSplitter)
7178 continue;
7180 BeginEnumPins(pBF, pEP, pPin)
7182 if(m_pCB->ChapGetCount()) break;
7184 if(CComQIPtr<IPropertyBag> pPB = pPin)
7186 for(int i = 1; ; i++)
7188 CStringW str;
7189 CComVariant var;
7191 var.Clear();
7192 str.Format(L"CHAPTER%02d", i);
7193 if(S_OK != pPB->Read(str, &var, NULL))
7194 break;
7196 int h, m, s, ms;
7197 WCHAR wc;
7198 if(7 != swscanf(CStringW(var), L"%d%c%d%c%d%c%d", &h, &wc, &m, &wc, &s, &wc, &ms))
7199 break;
7201 CStringW name;
7202 name.Format(L"Chapter %d", i);
7203 var.Clear();
7204 str += L"NAME";
7205 if(S_OK == pPB->Read(str, &var, NULL))
7206 name = var;
7208 m_pCB->ChapAppend(10000i64*(((h*60 + m)*60 + s)*1000 + ms), name);
7212 EndEnumPins
7215 m_pCB->ChapSort();
7218 void CMainFrame::OpenDVD(OpenDVDData* pODD)
7220 HRESULT hr = pGB->RenderFile(CStringW(pODD->path), NULL);
7222 AppSettings& s = AfxGetAppSettings();
7224 if(s.fReportFailedPins)
7226 CComQIPtr<IGraphBuilderDeadEnd> pGBDE = pGB;
7227 if(pGBDE && pGBDE->GetCount()) CMediaTypesDlg(pGBDE, this).DoModal();
7230 BeginEnumFilters(pGB, pEF, pBF)
7232 if((pDVDC = pBF) && (pDVDI = pBF))
7233 break;
7235 EndEnumFilters
7237 if(hr == E_INVALIDARG)
7238 throw _T("Cannot find DVD directory");
7239 else if(hr == VFW_E_CANNOT_RENDER)
7240 throw _T("Failed to render all pins of the DVD Navigator filter");
7241 else if(hr == VFW_S_PARTIAL_RENDER)
7242 throw _T("Failed to render some of the pins of the DVD Navigator filter");
7243 else if(hr == E_NOINTERFACE || !pDVDC || !pDVDI)
7244 throw _T("Failed to query the needed interfaces for DVD playback");
7245 else if(hr == VFW_E_CANNOT_LOAD_SOURCE_FILTER)
7246 throw _T("Can't create the DVD Navigator filter");
7247 else if(FAILED(hr))
7248 throw _T("Failed");
7250 WCHAR buff[MAX_PATH];
7251 ULONG len = 0;
7252 if(SUCCEEDED(hr = pDVDI->GetDVDDirectory(buff, countof(buff), &len)))
7253 pODD->title = CString(CStringW(buff));
7255 // TODO: resetdvd
7257 pDVDC->SetOption(DVD_ResetOnStop, FALSE);
7258 pDVDC->SetOption(DVD_HMSF_TimeCodeEvents, TRUE);
7260 if(s.idMenuLang) pDVDC->SelectDefaultMenuLanguage(s.idMenuLang);
7261 if(s.idAudioLang) pDVDC->SelectDefaultAudioLanguage(s.idAudioLang, DVD_AUD_EXT_NotSpecified);
7262 if(s.idSubtitlesLang) pDVDC->SelectDefaultSubpictureLanguage(s.idSubtitlesLang, DVD_SP_EXT_NotSpecified);
7264 m_iDVDDomain = DVD_DOMAIN_Stop;
7266 m_iPlaybackMode = PM_DVD;
7269 void CMainFrame::OpenCapture(OpenDeviceData* pODD)
7271 CStringW vidfrname, audfrname;
7272 CComPtr<IBaseFilter> pVidCapTmp, pAudCapTmp;
7274 m_VidDispName = pODD->DisplayName[0];
7276 if(!m_VidDispName.IsEmpty())
7278 if(!CreateFilter(m_VidDispName, &pVidCapTmp, vidfrname))
7279 throw _T("Can't create video capture filter");
7282 m_AudDispName = pODD->DisplayName[1];
7284 if(!m_AudDispName.IsEmpty())
7286 if(!CreateFilter(m_AudDispName, &pAudCapTmp, audfrname))
7287 throw _T("Can't create video capture filter");
7290 if(!pVidCapTmp && !pAudCapTmp)
7292 throw _T("No capture filters");
7295 pCGB = NULL;
7296 pVidCap = NULL;
7297 pAudCap = NULL;
7299 if(FAILED(pCGB.CoCreateInstance(CLSID_CaptureGraphBuilder2)))
7301 throw _T("Can't create capture graph builder object");
7304 HRESULT hr;
7306 pCGB->SetFiltergraph(pGB);
7308 if(pVidCapTmp)
7310 if(FAILED(hr = pGB->AddFilter(pVidCapTmp, vidfrname)))
7312 throw _T("Can't add video capture filter to the graph");
7315 pVidCap = pVidCapTmp;
7317 if(!pAudCapTmp)
7319 if(FAILED(pCGB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Interleaved, pVidCap, IID_IAMStreamConfig, (void **)&pAMVSCCap))
7320 && FAILED(pCGB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pVidCap, IID_IAMStreamConfig, (void **)&pAMVSCCap)))
7321 TRACE(_T("Warning: No IAMStreamConfig interface for vidcap capture"));
7323 if(FAILED(pCGB->FindInterface(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Interleaved, pVidCap, IID_IAMStreamConfig, (void **)&pAMVSCPrev))
7324 && FAILED(pCGB->FindInterface(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, pVidCap, IID_IAMStreamConfig, (void **)&pAMVSCPrev)))
7325 TRACE(_T("Warning: No IAMStreamConfig interface for vidcap capture"));
7327 if(FAILED(pCGB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, pVidCap, IID_IAMStreamConfig, (void **)&pAMASC))
7328 && FAILED(pCGB->FindInterface(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Audio, pVidCap, IID_IAMStreamConfig, (void **)&pAMASC)))
7330 TRACE(_T("Warning: No IAMStreamConfig interface for vidcap"));
7332 else
7334 pAudCap = pVidCap;
7337 else
7339 if(FAILED(pCGB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pVidCap, IID_IAMStreamConfig, (void **)&pAMVSCCap)))
7340 TRACE(_T("Warning: No IAMStreamConfig interface for vidcap capture"));
7342 if(FAILED(pCGB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pVidCap, IID_IAMStreamConfig, (void **)&pAMVSCPrev)))
7343 TRACE(_T("Warning: No IAMStreamConfig interface for vidcap capture"));
7346 if(FAILED(pCGB->FindInterface(&LOOK_UPSTREAM_ONLY, NULL, pVidCap, IID_IAMCrossbar, (void**)&pAMXBar)))
7347 TRACE(_T("Warning: No IAMCrossbar interface was found\n"));
7349 if(FAILED(pCGB->FindInterface(&LOOK_UPSTREAM_ONLY, NULL, pVidCap, IID_IAMTVTuner, (void**)&pAMTuner)))
7350 TRACE(_T("Warning: No IAMTVTuner interface was found\n"));
7352 if(pAMVSCCap)
7354 //DumpStreamConfig(_T("c:\\mpclog.txt"), pAMVSCCap);
7355 CComQIPtr<IAMVfwCaptureDialogs> pVfwCD = pVidCap;
7356 if(!pAMXBar && pVfwCD)
7358 m_wndCaptureBar.m_capdlg.SetupVideoControls(viddispname, pAMVSCCap, pVfwCD);
7360 else
7362 m_wndCaptureBar.m_capdlg.SetupVideoControls(viddispname, pAMVSCCap, pAMXBar, pAMTuner);
7366 // TODO: init pAMXBar
7368 if(pAMTuner) // load saved channel
7370 pAMTuner->put_CountryCode(AfxGetApp()->GetProfileInt(_T("Capture"), _T("Country"), 1));
7372 int vchannel = pODD->vchannel;
7373 if(vchannel < 0) vchannel = AfxGetApp()->GetProfileInt(_T("Capture\\") + CString(m_VidDispName), _T("Channel"), -1);
7374 if(vchannel >= 0)
7376 OAFilterState fs = State_Stopped;
7377 pMC->GetState(0, &fs);
7378 if(fs == State_Running) pMC->Pause();
7379 pAMTuner->put_Channel(vchannel, AMTUNER_SUBCHAN_DEFAULT, AMTUNER_SUBCHAN_DEFAULT);
7380 if(fs == State_Running) pMC->Run();
7385 if(pAudCapTmp)
7387 if(FAILED(hr = pGB->AddFilter(pAudCapTmp, CStringW(audfrname))))
7389 throw _T("Can't add audio capture filter to the graph");
7392 pAudCap = pAudCapTmp;
7394 if(FAILED(pCGB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, pAudCap, IID_IAMStreamConfig, (void **)&pAMASC))
7395 && FAILED(pCGB->FindInterface(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Audio, pAudCap, IID_IAMStreamConfig, (void **)&pAMASC)))
7397 TRACE(_T("Warning: No IAMStreamConfig interface for vidcap"));
7400 CInterfaceArray<IAMAudioInputMixer> pAMAIM;
7402 BeginEnumPins(pAudCap, pEP, pPin)
7404 PIN_DIRECTION dir;
7405 if(FAILED(pPin->QueryDirection(&dir)) || dir != PINDIR_INPUT)
7406 continue;
7408 if(CComQIPtr<IAMAudioInputMixer> pAIM = pPin)
7409 pAMAIM.Add(pAIM);
7411 EndEnumPins
7413 if(pAMASC)
7415 m_wndCaptureBar.m_capdlg.SetupAudioControls(auddispname, pAMASC, pAMAIM);
7420 if(!(pVidCap || pAudCap))
7422 throw _T("Couldn't open any device");
7425 pODD->title = _T("Live");
7427 m_iPlaybackMode = PM_CAPTURE;
7430 void CMainFrame::OpenCustomizeGraph()
7432 if(m_iPlaybackMode == PM_CAPTURE)
7433 return;
7435 CleanGraph();
7437 if(m_iPlaybackMode == PM_FILE)
7439 if(m_pCAP) {
7440 if(AfxGetAppSettings().fAutoloadSubtitles) {
7441 AddTextPassThruFilter();
7446 if(m_iPlaybackMode == PM_DVD)
7448 BeginEnumFilters(pGB, pEF, pBF)
7450 if(CComQIPtr<IDirectVobSub2> pDVS2 = pBF)
7452 // pDVS2->AdviseSubClock(m_pSubClock = new CSubClock);
7453 // break;
7455 // TODO: test multiple dvobsub instances with one clock
7456 if(!m_pSubClock) m_pSubClock = new CSubClock;
7457 pDVS2->AdviseSubClock(m_pSubClock);
7460 EndEnumFilters
7463 BeginEnumFilters(pGB, pEF, pBF)
7465 if(GetCLSID(pBF) == CLSID_OggSplitter)
7467 if(CComQIPtr<IAMStreamSelect> pSS = pBF)
7469 LCID idAudio = AfxGetAppSettings().idAudioLang;
7470 if(!idAudio) idAudio = GetUserDefaultLCID();
7471 LCID idSub = AfxGetAppSettings().idSubtitlesLang;
7472 if(!idSub) idSub = GetUserDefaultLCID();
7474 DWORD cnt = 0;
7475 pSS->Count(&cnt);
7476 for(DWORD i = 0; i < cnt; i++)
7478 AM_MEDIA_TYPE* pmt = NULL;
7479 DWORD dwFlags = 0;
7480 LCID lcid = 0;
7481 DWORD dwGroup = 0;
7482 WCHAR* pszName = NULL;
7483 if(SUCCEEDED(pSS->Info((long)i, &pmt, &dwFlags, &lcid, &dwGroup, &pszName, NULL, NULL)))
7485 CStringW name(pszName), sound(L"Sound"), subtitle(L"Subtitle");
7487 if(idAudio != -1 && (idAudio&0x3ff) == (lcid&0x3ff) // sublang seems to be zeroed out in ogm...
7488 && name.GetLength() > sound.GetLength()
7489 && !name.Left(sound.GetLength()).CompareNoCase(sound))
7491 if(SUCCEEDED(pSS->Enable(i, AMSTREAMSELECTENABLE_ENABLE)))
7492 idAudio = -1;
7495 if(idSub != -1 && (idSub&0x3ff) == (lcid&0x3ff) // sublang seems to be zeroed out in ogm...
7496 && name.GetLength() > subtitle.GetLength()
7497 && !name.Left(subtitle.GetLength()).CompareNoCase(subtitle)
7498 && name.Mid(subtitle.GetLength()).Trim().CompareNoCase(L"off"))
7500 if(SUCCEEDED(pSS->Enable(i, AMSTREAMSELECTENABLE_ENABLE)))
7501 idSub = -1;
7504 if(pmt) DeleteMediaType(pmt);
7505 if(pszName) CoTaskMemFree(pszName);
7511 EndEnumFilters
7513 CleanGraph();
7516 void CMainFrame::OpenSetupVideo()
7518 m_fAudioOnly = true;
7520 if(m_pCAP)
7522 CSize vs = m_pCAP->GetVideoSize();
7523 m_fAudioOnly = (vs.cx <= 0 || vs.cy <= 0);
7525 else
7528 long w = 0, h = 0;
7530 if(CComQIPtr<IBasicVideo> pBV = pGB)
7532 pBV->GetVideoSize(&w, &h);
7535 if(w > 0 && h > 0)
7537 m_fAudioOnly = false;
7541 if(m_fAudioOnly)
7543 BeginEnumFilters(pGB, pEF, pBF)
7545 long w = 0, h = 0;
7547 if(CComQIPtr<IVideoWindow> pVW = pBF)
7549 long lVisible;
7550 if(FAILED(pVW->get_Visible(&lVisible)))
7551 continue;
7553 pVW->get_Width(&w);
7554 pVW->get_Height(&h);
7557 if(w > 0 && h > 0)
7559 m_fAudioOnly = false;
7560 break;
7563 EndEnumFilters
7567 if(m_fShockwaveGraph)
7569 m_fAudioOnly = false;
7572 if(m_pCAP)
7574 SetShaders();
7576 // else
7578 // TESTME
7580 pVW->put_Owner((OAHWND)m_wndView.m_hWnd);
7581 pVW->put_WindowStyle(WS_CHILD|WS_CLIPSIBLINGS|WS_CLIPCHILDREN);
7582 pVW->put_MessageDrain((OAHWND)m_hWnd);
7584 for(CWnd* pWnd = m_wndView.GetWindow(GW_CHILD); pWnd; pWnd = pWnd->GetNextWindow())
7585 pWnd->EnableWindow(FALSE); // little trick to let WM_SETCURSOR thru
7589 void CMainFrame::OpenSetupAudio()
7591 pBA->put_Volume(m_wndToolBar.Volume);
7593 // FIXME
7594 int balance = AfxGetAppSettings().nBalance;
7595 int sign = balance>0?-1:1;
7596 balance = max(100-abs(balance), 1);
7597 balance = (int)((log10(1.0*balance)-2)*5000*sign);
7598 balance = max(min(balance, 10000), -10000);
7599 pBA->put_Balance(balance);
7602 void CMainFrame::OpenSetupToolBar()
7604 // m_wndToolBar.Volume = AfxGetAppSettings().nVolume;
7605 // SetBalance(AfxGetAppSettings().nBalance);
7608 void CMainFrame::OpenSetupCaptureBar()
7610 if(m_iPlaybackMode == PM_CAPTURE)
7612 if(pVidCap && pAMVSCCap)
7614 CComQIPtr<IAMVfwCaptureDialogs> pVfwCD = pVidCap;
7616 if(!pAMXBar && pVfwCD)
7618 m_wndCaptureBar.m_capdlg.SetupVideoControls(m_VidDispName, pAMVSCCap, pVfwCD);
7620 else
7622 m_wndCaptureBar.m_capdlg.SetupVideoControls(m_VidDispName, pAMVSCCap, pAMXBar, pAMTuner);
7626 if(pAudCap && pAMASC)
7628 CInterfaceArray<IAMAudioInputMixer> pAMAIM;
7630 BeginEnumPins(pAudCap, pEP, pPin)
7632 if(CComQIPtr<IAMAudioInputMixer> pAIM = pPin)
7633 pAMAIM.Add(pAIM);
7635 EndEnumPins
7637 m_wndCaptureBar.m_capdlg.SetupAudioControls(m_AudDispName, pAMASC, pAMAIM);
7641 BuildGraphVideoAudio(
7642 m_wndCaptureBar.m_capdlg.m_fVidPreview, false,
7643 m_wndCaptureBar.m_capdlg.m_fAudPreview, false);
7646 void CMainFrame::OpenSetupInfoBar()
7648 if(m_iPlaybackMode == PM_FILE)
7650 bool fEmpty = true;
7651 BeginEnumFilters(pGB, pEF, pBF)
7653 if(CComQIPtr<IAMMediaContent, &IID_IAMMediaContent> pAMMC = pBF)
7655 CComBSTR bstr;
7656 if(SUCCEEDED(pAMMC->get_Title(&bstr))) {m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_TITLE), bstr.m_str); if(bstr.Length()) fEmpty = false;}
7657 if(SUCCEEDED(pAMMC->get_AuthorName(&bstr))) {m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_AUTHOR), bstr.m_str); if(bstr.Length()) fEmpty = false;}
7658 if(SUCCEEDED(pAMMC->get_Copyright(&bstr))) {m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_COPYRIGHT), bstr.m_str); if(bstr.Length()) fEmpty = false;}
7659 if(SUCCEEDED(pAMMC->get_Rating(&bstr))) {m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_RATING), bstr.m_str); if(bstr.Length()) fEmpty = false;}
7660 if(SUCCEEDED(pAMMC->get_Description(&bstr))) {m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_DESCRIPTION), bstr.m_str); if(bstr.Length()) fEmpty = false;}
7661 if(!fEmpty)
7663 RecalcLayout();
7664 break;
7668 EndEnumFilters
7670 else if(m_iPlaybackMode == PM_DVD)
7672 CString info('-');
7673 m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_DOMAIN), info);
7674 m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_LOCATION), info);
7675 m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_VIDEO), info);
7676 m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_AUDIO), info);
7677 m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_SUBTITLES), info);
7678 RecalcLayout();
7682 void CMainFrame::OpenSetupStatsBar()
7684 CString info('-');
7686 BeginEnumFilters(pGB, pEF, pBF)
7688 if(!pQP && (pQP = pBF))
7690 m_wndStatsBar.SetLine(_T("Frame-rate"), info);
7691 m_wndStatsBar.SetLine(_T("Sync Offset"), info);
7692 m_wndStatsBar.SetLine(_T("Frames"), info);
7693 m_wndStatsBar.SetLine(_T("Jitter"), info);
7694 m_wndStatsBar.SetLine(_T("Buffers"), info);
7695 m_wndStatsBar.SetLine(_T("Bitrate"), info);
7696 RecalcLayout();
7699 if(!pBI && (pBI = pBF))
7701 m_wndStatsBar.SetLine(_T("Buffers"), info);
7702 m_wndStatsBar.SetLine(_T("Bitrate"), info); // FIXME: shouldn't be here
7703 RecalcLayout();
7706 EndEnumFilters
7709 void CMainFrame::OpenSetupStatusBar()
7711 m_wndStatusBar.ShowTimer(true);
7715 if(!m_fCustomGraph)
7717 UINT id = IDB_NOAUDIO;
7719 BeginEnumFilters(pGB, pEF, pBF)
7721 CComQIPtr<IBasicAudio> pBA = pBF;
7722 if(!pBA) continue;
7724 BeginEnumPins(pBF, pEP, pPin)
7726 if(S_OK == pGB->IsPinDirection(pPin, PINDIR_INPUT)
7727 && S_OK == pGB->IsPinConnected(pPin))
7729 AM_MEDIA_TYPE mt;
7730 memset(&mt, 0, sizeof(mt));
7731 pPin->ConnectionMediaType(&mt);
7733 if(mt.majortype == MEDIATYPE_Audio && mt.formattype == FORMAT_WaveFormatEx)
7735 switch(((WAVEFORMATEX*)mt.pbFormat)->nChannels)
7737 case 1: id = IDB_MONO; break;
7738 case 2: default: id = IDB_STEREO; break;
7740 break;
7742 else if(mt.majortype == MEDIATYPE_Midi)
7744 id = NULL;
7745 break;
7749 EndEnumPins
7751 if(id != IDB_NOAUDIO)
7753 break;
7756 EndEnumFilters
7758 m_wndStatusBar.SetStatusBitmap(id);
7763 HICON hIcon = NULL;
7765 if(m_iPlaybackMode == PM_FILE)
7767 CString fn = m_wndPlaylistBar.GetCur();
7768 CString ext = fn.Mid(fn.ReverseFind('.')+1);
7769 hIcon = LoadIcon(ext, true);
7771 else if(m_iPlaybackMode == PM_DVD)
7773 hIcon = LoadIcon(_T(".ifo"), true);
7775 else if(m_iPlaybackMode == PM_DVD)
7777 // hIcon = ; // TODO
7780 m_wndStatusBar.SetStatusTypeIcon(hIcon);
7783 void CMainFrame::OpenSetupWindowTitle(CString fn)
7785 CString title(MAKEINTRESOURCE(IDR_MAINFRAME));
7787 AppSettings& s = AfxGetAppSettings();
7789 int i = s.iTitleBarTextStyle;
7791 if(!fn.IsEmpty() && (i == 0 || i == 1))
7793 if(i == 1)
7795 if(m_iPlaybackMode == PM_FILE)
7797 fn.Replace('\\', '/');
7798 CString fn2 = fn.Mid(fn.ReverseFind('/')+1);
7799 if(!fn2.IsEmpty()) fn = fn2;
7801 if(s.fTitleBarTextTitle)
7803 BeginEnumFilters(pGB, pEF, pBF)
7805 if(CComQIPtr<IAMMediaContent, &IID_IAMMediaContent> pAMMC = pBF)
7807 CComBSTR bstr;
7808 if(SUCCEEDED(pAMMC->get_Title(&bstr)) && bstr.Length())
7810 fn = CString(bstr.m_str);
7811 break;
7815 EndEnumFilters
7818 else if(m_iPlaybackMode == PM_DVD)
7820 fn = _T("DVD");
7822 else if(m_iPlaybackMode == PM_CAPTURE)
7824 fn = _T("Live");
7828 title = fn + _T(" - ") + title;
7831 SetWindowText(title);
7834 bool CMainFrame::OpenMediaPrivate(CAutoPtr<OpenMediaData> pOMD)
7836 if(m_iMediaLoadState != MLS_CLOSED && m_iMediaLoadState != MLS_LOADING)
7838 ASSERT(0);
7839 return(false);
7842 m_iMediaLoadState = MLS_LOADING;
7844 // FIXME: Don't show "Closed" initially
7845 PostMessage(WM_KICKIDLE);
7847 CString err, aborted(_T("Aborted"));
7849 m_fUpdateInfoBar = false;
7853 if(m_fOpeningAborted) throw aborted;
7855 if(OpenFileData* pOFD = dynamic_cast<OpenFileData*>(pOMD.m_p))
7857 if(pOFD->fns.IsEmpty()) throw _T("File not found");
7859 CString fn = pOFD->fns.GetHead();
7861 int i = fn.Find(_T(":\\"));
7862 if(i > 0)
7864 CString drive = fn.Left(i+2);
7865 UINT type = GetDriveType(drive);
7866 CAtlList<CString> sl;
7867 if(type == DRIVE_REMOVABLE || type == DRIVE_CDROM && GetCDROMType(drive[0], sl) != CDROM_Audio)
7869 int ret = IDRETRY;
7870 while(ret == IDRETRY)
7872 WIN32_FIND_DATA findFileData;
7873 HANDLE h = FindFirstFile(fn, &findFileData);
7874 if(h != INVALID_HANDLE_VALUE)
7876 FindClose(h);
7877 ret = IDOK;
7879 else
7881 CString msg;
7882 msg.Format(_T("%s was not found, please insert media containing this file."), fn);
7883 ret = AfxMessageBox(msg, MB_RETRYCANCEL);
7887 if(ret != IDOK) throw aborted;
7892 if(m_fOpeningAborted) throw aborted;
7894 OpenCreateGraphObject(pOMD);
7896 if(m_fOpeningAborted) throw aborted;
7898 SetupIViAudReg();
7900 if(m_fOpeningAborted) throw aborted;
7902 if(OpenFileData* p = dynamic_cast<OpenFileData*>(pOMD.m_p)) OpenFile(p);
7903 else if(OpenDVDData* p = dynamic_cast<OpenDVDData*>(pOMD.m_p)) OpenDVD(p);
7904 else if(OpenDeviceData* p = dynamic_cast<OpenDeviceData*>(pOMD.m_p)) OpenCapture(p);
7905 else throw _T("Can't open, invalid input parameters");
7907 pGB->FindInterface(__uuidof(ISubPicAllocatorPresenter), (void**)&m_pCAP, TRUE);
7909 if(m_fOpeningAborted) throw aborted;
7911 OpenCustomizeGraph();
7913 if(m_fOpeningAborted) throw aborted;
7915 OpenSetupVideo();
7917 if(m_fOpeningAborted) throw aborted;
7919 OpenSetupAudio();
7921 if(m_fOpeningAborted) throw aborted;
7923 if(m_pCAP && (!m_fAudioOnly || m_fRealMediaGraph))
7925 POSITION pos = pOMD->subs.GetHeadPosition();
7926 while(pos) LoadSubtitle(pOMD->subs.GetNext(pos));
7928 if(AfxGetAppSettings().fEnableSubtitles && m_pSubStreams.GetCount() > 0)
7929 SetSubtitle(m_pSubStreams.GetHead());
7932 if(m_fOpeningAborted) throw aborted;
7934 OpenSetupWindowTitle(pOMD->title);
7936 if(::GetCurrentThreadId() == AfxGetApp()->m_nThreadID)
7938 OnFilePostOpenmedia();
7940 else
7942 PostMessage(WM_COMMAND, ID_FILE_POST_OPENMEDIA);
7945 while(m_iMediaLoadState != MLS_LOADED
7946 && m_iMediaLoadState != MLS_CLOSING // FIXME
7949 Sleep(50);
7952 // PostMessage instead of SendMessage because the user might call CloseMedia and then we would deadlock
7954 PostMessage(WM_COMMAND, ID_PLAY_PAUSE);
7956 if(!(AfxGetAppSettings().nCLSwitches&CLSW_OPEN))
7957 PostMessage(WM_COMMAND, ID_PLAY_PLAY);
7959 AfxGetAppSettings().nCLSwitches &= ~CLSW_OPEN;
7961 if(OpenFileData* p = dynamic_cast<OpenFileData*>(pOMD.m_p))
7963 if(p->rtStart > 0)
7964 PostMessage(WM_RESUMEFROMSTATE, (WPARAM)PM_FILE, (LPARAM)(p->rtStart/10000)); // REFERENCE_TIME doesn't fit in LPARAM under a 32bit env.
7966 else if(OpenDVDData* p = dynamic_cast<OpenDVDData*>(pOMD.m_p))
7968 if(p->pDvdState)
7969 PostMessage(WM_RESUMEFROMSTATE, (WPARAM)PM_DVD, (LPARAM)(CComPtr<IDvdState>(p->pDvdState).Detach())); // must be released by the called message handler
7971 else if(OpenDeviceData* p = dynamic_cast<OpenDeviceData*>(pOMD.m_p))
7973 m_wndCaptureBar.m_capdlg.SetVideoInput(p->vinput);
7974 m_wndCaptureBar.m_capdlg.SetVideoChannel(p->vchannel);
7975 m_wndCaptureBar.m_capdlg.SetAudioInput(p->ainput);
7978 catch(LPCTSTR msg)
7980 err = msg;
7982 catch(CString msg)
7984 err = msg;
7987 if(!err.IsEmpty())
7989 CloseMediaPrivate();
7990 m_closingmsg = err;
7992 OpenFileData* p = dynamic_cast<OpenFileData*>(pOMD.m_p);
7993 if(p && err != aborted)
7995 m_wndPlaylistBar.SetCurValid(false);
7996 if(m_wndPlaylistBar.GetCount() > 1)
7998 CPlaylistItem pli[2];
7999 m_wndPlaylistBar.GetCur(pli[0]);
8000 m_wndPlaylistBar.SetNext();
8001 m_wndPlaylistBar.GetCur(pli[1]);
8002 if(pli[0].m_id != pli[1].m_id)
8004 CAutoPtr<OpenMediaData> p(m_wndPlaylistBar.GetCurOMD());
8005 if(p) OpenMediaPrivate(p);
8010 else
8012 m_wndPlaylistBar.SetCurValid(true);
8015 PostMessage(WM_KICKIDLE); // calls main thread to update things
8017 return(err.IsEmpty());
8020 void CMainFrame::CloseMediaPrivate()
8022 m_iMediaLoadState = MLS_CLOSING;
8024 OnPlayStop(); // SendMessage(WM_COMMAND, ID_PLAY_STOP);
8026 m_iPlaybackMode = PM_NONE;
8027 m_iSpeedLevel = 0;
8029 m_fLiveWM = false;
8031 m_fEndOfStream = false;
8033 m_rtDurationOverride = -1;
8035 m_kfs.RemoveAll();
8037 m_pCB = NULL;
8039 // if(pVW) pVW->put_Visible(OAFALSE);
8040 // if(pVW) pVW->put_MessageDrain((OAHWND)NULL), pVW->put_Owner((OAHWND)NULL);
8042 m_pCAP = NULL; // IMPORTANT: IVMRSurfaceAllocatorNotify/IVMRSurfaceAllocatorNotify9 has to be released before the VMR/VMR9, otherwise it will crash in Release()
8044 pAMXBar.Release(); pAMTuner.Release(); pAMDF.Release();
8045 pAMVCCap.Release(); pAMVCPrev.Release(); pAMVSCCap.Release(); pAMVSCPrev.Release(); pAMASC.Release();
8046 pVidCap.Release(); pAudCap.Release();
8047 pCGB.Release();
8048 pDVDC.Release(); pDVDI.Release();
8049 pQP.Release(); pBI.Release(); pAMOP.Release(); pFS.Release();
8050 pMC.Release(); pME.Release(); pMS.Release();
8051 pVW.Release(); pBV.Release();
8052 pBA.Release();
8054 if(pGB) pGB->RemoveFromROT();
8055 pGB.Release();
8057 m_fRealMediaGraph = m_fShockwaveGraph = m_fQuicktimeGraph = false;
8059 m_pSubClock = NULL;
8061 m_pProv.Release();
8064 CAutoLock cAutoLock(&m_csSubLock);
8065 m_pSubStreams.RemoveAll();
8068 m_VidDispName.Empty();
8069 m_AudDispName.Empty();
8071 m_closingmsg = ResStr(IDS_CONTROLS_CLOSED);
8073 AfxGetAppSettings().nCLSwitches &= CLSW_OPEN|CLSW_PLAY|CLSW_AFTERPLAYBACK_MASK|CLSW_NOFOCUS;
8075 m_iMediaLoadState = MLS_CLOSED;
8078 // msn
8080 void CMainFrame::SendNowPlayingToMSN()
8082 if(!AfxGetAppSettings().fNotifyMSN)
8083 return;
8085 CString title, author;
8087 if(m_iMediaLoadState == MLS_LOADED)
8089 m_wndInfoBar.GetLine(ResStr(IDS_INFOBAR_TITLE), title);
8090 m_wndInfoBar.GetLine(ResStr(IDS_INFOBAR_AUTHOR), author);
8092 if(title.IsEmpty())
8094 CPlaylistItem pli;
8095 m_wndPlaylistBar.GetCur(pli);
8097 if(!pli.m_fns.IsEmpty())
8099 CString label = !pli.m_label.IsEmpty() ? pli.m_label : pli.m_fns.GetHead();
8101 if(m_iPlaybackMode == PM_FILE)
8103 CString fn = label;
8104 if(fn.Find(_T("://")) >= 0) {int i = fn.Find('?'); if(i >= 0) fn = fn.Left(i);}
8105 CPath path(fn);
8106 path.StripPath();
8107 path.MakePretty();
8108 path.RemoveExtension();
8109 title = (LPCTSTR)path;
8110 author.Empty();
8112 else if(m_iPlaybackMode == PM_CAPTURE)
8114 title = label != pli.m_fns.GetHead() ? label : _T("Live");
8115 author.Empty();
8117 else if(m_iPlaybackMode == PM_DVD)
8119 title = _T("DVD");
8120 author.Empty();
8126 CStringW buff;
8127 buff += L"\\0Music\\0";
8128 buff += title.IsEmpty() ? L"0" : L"1";
8129 buff += L"\\0";
8130 buff += author.IsEmpty() ? L"{0}" : L"{0} - {1}";
8131 buff += L"\\0";
8132 if(!author.IsEmpty()) {buff += CStringW(author) + L"\\0";}
8133 buff += CStringW(title) + L"\\0";
8134 buff += L"\\0\\0";
8136 COPYDATASTRUCT data;
8137 data.dwData = 0x0547;
8138 data.lpData = (PVOID)(LPCWSTR)buff;
8139 data.cbData = buff.GetLength() * 2 + 2;
8141 HWND hWnd = NULL;
8142 while(hWnd = ::FindWindowEx(NULL, hWnd, _T("MsnMsgrUIManager"), NULL))
8143 ::SendMessage(hWnd, WM_COPYDATA, (WPARAM)NULL, (LPARAM)&data);
8146 // mIRC
8148 void CMainFrame::SendNowPlayingTomIRC()
8150 if(!AfxGetAppSettings().fNotifyGTSdll)
8151 return;
8153 for(int i = 0; i < 20; i++)
8155 HANDLE hFMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 1024, _T("mIRC"));
8156 if(!hFMap) return;
8158 if(GetLastError() == ERROR_ALREADY_EXISTS)
8160 CloseHandle(hFMap);
8161 Sleep(50);
8162 continue;
8165 if(LPVOID lpMappingAddress = MapViewOfFile(hFMap, FILE_MAP_WRITE, 0, 0, 0))
8167 LPCSTR cmd = m_fAudioOnly ? "/.timerAUDGTS 1 5 mpcaud" : "/.timerVIDGTS 1 5 mpcvid";
8168 strcpy((char*)lpMappingAddress, cmd);
8170 if(HWND hWnd = ::FindWindow(_T("mIRC"), NULL))
8171 ::SendMessage(hWnd, (WM_USER + 200), (WPARAM)1, (LPARAM)0);
8173 UnmapViewOfFile(lpMappingAddress);
8176 CloseHandle(hFMap);
8178 break;
8182 // dynamic menus
8184 void CMainFrame::SetupOpenCDSubMenu()
8186 CMenu* pSub = &m_opencds;
8188 if(!IsMenu(pSub->m_hMenu)) pSub->CreatePopupMenu();
8189 else while(pSub->RemoveMenu(0, MF_BYPOSITION));
8191 if(m_iMediaLoadState == MLS_LOADING) return;
8193 if(AfxGetAppSettings().fHideCDROMsSubMenu) return;
8195 UINT id = ID_FILE_OPEN_CD_START;
8197 for(TCHAR drive = 'C'; drive <= 'Z'; drive++)
8199 CString label = GetDriveLabel(drive), str;
8201 CAtlList<CString> files;
8202 switch(GetCDROMType(drive, files))
8204 case CDROM_Audio:
8205 if(label.IsEmpty()) label = _T("Audio CD");
8206 str.Format(_T("%s (%c:)"), label, drive);
8207 break;
8208 case CDROM_VideoCD:
8209 if(label.IsEmpty()) label = _T("(S)VCD");
8210 str.Format(_T("%s (%c:)"), label, drive);
8211 break;
8212 case CDROM_DVDVideo:
8213 if(label.IsEmpty()) label = _T("DVD Video");
8214 str.Format(_T("%s (%c:)"), label, drive);
8215 break;
8216 default:
8217 break;
8220 if(!str.IsEmpty())
8221 pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, str);
8225 void CMainFrame::SetupFiltersSubMenu()
8227 CMenu* pSub = &m_filters;
8229 if(!IsMenu(pSub->m_hMenu)) pSub->CreatePopupMenu();
8230 else while(pSub->RemoveMenu(0, MF_BYPOSITION));
8232 m_filterpopups.RemoveAll();
8234 m_pparray.RemoveAll();
8235 m_ssarray.RemoveAll();
8237 if(m_iMediaLoadState == MLS_LOADED)
8239 UINT idf = 0;
8240 UINT ids = ID_FILTERS_SUBITEM_START;
8241 UINT idl = ID_FILTERSTREAMS_SUBITEM_START;
8243 BeginEnumFilters(pGB, pEF, pBF)
8245 CString name(GetFilterName(pBF));
8246 if(name.GetLength() >= 43) name = name.Left(40) + _T("...");
8248 CLSID clsid = GetCLSID(pBF);
8249 if(clsid == CLSID_AVIDec)
8251 CComPtr<IPin> pPin = GetFirstPin(pBF);
8252 AM_MEDIA_TYPE mt;
8253 if(pPin && SUCCEEDED(pPin->ConnectionMediaType(&mt)))
8255 DWORD c = ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biCompression;
8256 switch(c)
8258 case BI_RGB: name += _T(" (RGB)"); break;
8259 case BI_RLE4: name += _T(" (RLE4)"); break;
8260 case BI_RLE8: name += _T(" (RLE8)"); break;
8261 case BI_BITFIELDS: name += _T(" (BITF)"); break;
8262 default: name.Format(_T("%s (%c%c%c%c)"),
8263 CString(name), (TCHAR)((c>>0)&0xff), (TCHAR)((c>>8)&0xff), (TCHAR)((c>>16)&0xff), (TCHAR)((c>>24)&0xff)); break;
8267 else if(clsid == CLSID_ACMWrapper)
8269 CComPtr<IPin> pPin = GetFirstPin(pBF);
8270 AM_MEDIA_TYPE mt;
8271 if(pPin && SUCCEEDED(pPin->ConnectionMediaType(&mt)))
8273 WORD c = ((WAVEFORMATEX*)mt.pbFormat)->wFormatTag;
8274 name.Format(_T("%s (0x%04x)"), CString(name), (int)c);
8277 else if(clsid == __uuidof(CTextPassThruFilter) || clsid == __uuidof(CNullTextRenderer)
8278 || clsid == GUIDFromCString(_T("{48025243-2D39-11CE-875D-00608CB78066}"))) // ISCR
8280 // hide these
8281 continue;
8284 CAutoPtr<CMenu> pSubSub(new CMenu);
8285 pSubSub->CreatePopupMenu();
8287 int nPPages = 0;
8289 CComQIPtr<ISpecifyPropertyPages> pSPP = pBF;
8291 /* if(pSPP)
8293 CAUUID caGUID;
8294 caGUID.pElems = NULL;
8295 if(SUCCEEDED(pSPP->GetPages(&caGUID)) && caGUID.cElems > 0)
8297 */ m_pparray.Add(pBF);
8298 pSubSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, ids, _T("&Properties..."));
8300 if(caGUID.pElems) CoTaskMemFree(caGUID.pElems);
8302 nPPages++;
8303 /* }
8306 BeginEnumPins(pBF, pEP, pPin)
8308 CString name = GetPinName(pPin);
8309 name.Replace(_T("&"), _T("&&"));
8311 if(pSPP = pPin)
8313 CAUUID caGUID;
8314 caGUID.pElems = NULL;
8315 if(SUCCEEDED(pSPP->GetPages(&caGUID)) && caGUID.cElems > 0)
8317 m_pparray.Add(pPin);
8318 pSubSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, ids+nPPages, name + _T(" (pin) properties..."));
8320 if(caGUID.pElems) CoTaskMemFree(caGUID.pElems);
8322 nPPages++;
8326 EndEnumPins
8328 CComQIPtr<IAMStreamSelect> pSS = pBF;
8329 if(pSS)
8331 DWORD nStreams = 0, flags, group, prevgroup = -1;
8332 LCID lcid;
8333 WCHAR* wname = NULL;
8334 CComPtr<IUnknown> pObj, pUnk;
8336 pSS->Count(&nStreams);
8338 if(nStreams > 0 && nPPages > 0) pSubSub->AppendMenu(MF_SEPARATOR|MF_ENABLED);
8340 UINT idlstart = idl;
8342 for(DWORD i = 0; i < nStreams; i++, pObj = NULL, pUnk = NULL)
8344 m_ssarray.Add(pSS);
8346 flags = group = 0;
8347 wname = NULL;
8348 pSS->Info(i, NULL, &flags, &lcid, &group, &wname, &pObj, &pUnk);
8350 if(group != prevgroup && idl > idlstart)
8351 pSubSub->AppendMenu(MF_SEPARATOR|MF_ENABLED);
8352 prevgroup = group;
8354 if(flags & AMSTREAMSELECTINFO_EXCLUSIVE)
8357 else if(flags & AMSTREAMSELECTINFO_ENABLED)
8361 if(!wname)
8363 CStringW stream(L"Unknown Stream");
8364 wname = (WCHAR*)CoTaskMemAlloc((stream.GetLength()+3+1)*sizeof(WCHAR));
8365 swprintf(wname, L"%s %d", stream, min(i+1,999));
8368 CString name(wname);
8369 name.Replace(_T("&"), _T("&&"));
8371 pSubSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, idl++, name);
8373 CoTaskMemFree(wname);
8376 if(nStreams == 0) pSS.Release();
8379 if(nPPages == 1 && !pSS)
8381 pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, ids, name);
8383 else
8385 pSub->AppendMenu(MF_BYPOSITION|MF_STRING|MF_DISABLED|MF_GRAYED, idf, name);
8387 if(nPPages > 0 || pSS)
8389 MENUITEMINFO mii;
8390 mii.cbSize = sizeof(mii);
8391 mii.fMask = MIIM_STATE|MIIM_SUBMENU;
8392 mii.fType = MF_POPUP;
8393 mii.hSubMenu = pSubSub->m_hMenu;
8394 mii.fState = (pSPP || pSS) ? MF_ENABLED : (MF_DISABLED|MF_GRAYED);
8395 pSub->SetMenuItemInfo(idf, &mii, TRUE);
8397 m_filterpopups.Add(pSubSub);
8401 ids += nPPages;
8402 idf++;
8404 EndEnumFilters
8408 void CMainFrame::SetupAudioSwitcherSubMenu()
8410 CMenu* pSub = &m_audios;
8412 if(!IsMenu(pSub->m_hMenu)) pSub->CreatePopupMenu();
8413 else while(pSub->RemoveMenu(0, MF_BYPOSITION));
8415 if(m_iMediaLoadState == MLS_LOADED)
8417 UINT id = ID_AUDIO_SUBITEM_START;
8419 CComQIPtr<IAMStreamSelect> pSS = FindFilter(__uuidof(CAudioSwitcherFilter), pGB);
8420 if(!pSS) pSS = FindFilter(L"{D3CD7858-971A-4838-ACEC-40CA5D529DC8}", pGB);
8422 if(pSS)
8424 DWORD cStreams = 0;
8425 if(SUCCEEDED(pSS->Count(&cStreams)) && cStreams > 0)
8427 pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, ResStr(IDS_SUBTITLES_OPTIONS));
8428 pSub->AppendMenu(MF_SEPARATOR|MF_ENABLED);
8430 for(int i = 0; i < (int)cStreams; i++)
8432 WCHAR* pName = NULL;
8433 if(FAILED(pSS->Info(i, NULL, NULL, NULL, NULL, &pName, NULL, NULL)))
8434 break;
8436 CString name(pName);
8437 name.Replace(_T("&"), _T("&&"));
8439 pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, name);
8441 CoTaskMemFree(pName);
8448 void CMainFrame::SetupSubtitlesSubMenu()
8450 CMenu* pSub = &m_subtitles;
8452 if(!IsMenu(pSub->m_hMenu)) pSub->CreatePopupMenu();
8453 else while(pSub->RemoveMenu(0, MF_BYPOSITION));
8455 if(m_iMediaLoadState != MLS_LOADED || m_fAudioOnly || !m_pCAP)
8456 return;
8458 UINT id = ID_SUBTITLES_SUBITEM_START;
8460 POSITION pos = m_pSubStreams.GetHeadPosition();
8462 if(pos)
8464 pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, ResStr(IDS_SUBTITLES_OPTIONS));
8465 pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, ResStr(IDS_SUBTITLES_STYLES));
8466 pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, ResStr(IDS_SUBTITLES_RELOAD));
8467 pSub->AppendMenu(MF_SEPARATOR);
8469 pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, ResStr(IDS_SUBTITLES_ENABLE));
8470 pSub->AppendMenu(MF_SEPARATOR);
8473 while(pos)
8475 CComPtr<ISubStream> pSubStream = m_pSubStreams.GetNext(pos);
8476 if(!pSubStream) continue;
8478 for(int i = 0, j = pSubStream->GetStreamCount(); i < j; i++)
8480 WCHAR* pName = NULL;
8481 if(SUCCEEDED(pSubStream->GetStreamInfo(i, &pName, NULL)))
8483 CString name(pName);
8484 name.Replace(_T("&"), _T("&&"));
8486 pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, name);
8487 CoTaskMemFree(pName);
8489 else
8491 pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, _T("<Unknown>"));
8495 // TODO: find a better way to group these entries
8496 if(pos && m_pSubStreams.GetAt(pos))
8498 CLSID cur, next;
8499 pSubStream->GetClassID(&cur);
8500 m_pSubStreams.GetAt(pos)->GetClassID(&next);
8502 if(cur != next)
8503 pSub->AppendMenu(MF_SEPARATOR);
8508 void CMainFrame::SetupNavAudioSubMenu()
8510 CMenu* pSub = &m_navaudio;
8512 if(!IsMenu(pSub->m_hMenu)) pSub->CreatePopupMenu();
8513 else while(pSub->RemoveMenu(0, MF_BYPOSITION));
8515 if(m_iMediaLoadState != MLS_LOADED) return;
8517 UINT id = ID_NAVIGATE_AUDIO_SUBITEM_START;
8519 if(m_iPlaybackMode == PM_FILE)
8521 SetupNavStreamSelectSubMenu(pSub, id, 1);
8523 else if(m_iPlaybackMode == PM_DVD)
8525 ULONG ulStreamsAvailable, ulCurrentStream;
8526 if(FAILED(pDVDI->GetCurrentAudio(&ulStreamsAvailable, &ulCurrentStream)))
8527 return;
8529 LCID DefLanguage;
8530 DVD_AUDIO_LANG_EXT ext;
8531 if(FAILED(pDVDI->GetDefaultAudioLanguage(&DefLanguage, &ext)))
8532 return;
8534 for(ULONG i = 0; i < ulStreamsAvailable; i++)
8536 LCID Language;
8537 if(FAILED(pDVDI->GetAudioLanguage(i, &Language)))
8538 continue;
8540 UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
8541 if(Language == DefLanguage) flags |= MF_DEFAULT;
8542 if(i == ulCurrentStream) flags |= MF_CHECKED;
8544 CString str(_T("Unknown"));
8545 if(Language)
8547 int len = GetLocaleInfo(Language, LOCALE_SENGLANGUAGE, str.GetBuffer(256), 256);
8548 str.ReleaseBufferSetLength(max(len-1, 0));
8551 DVD_AudioAttributes ATR;
8552 if(SUCCEEDED(pDVDI->GetAudioAttributes(i, &ATR)))
8554 switch(ATR.LanguageExtension)
8556 case DVD_AUD_EXT_NotSpecified:
8557 default: break;
8558 case DVD_AUD_EXT_Captions: str += _T(" (Captions)"); break;
8559 case DVD_AUD_EXT_VisuallyImpaired: str += _T(" (Visually Impaired)"); break;
8560 case DVD_AUD_EXT_DirectorComments1: str += _T(" (Director Comments 1)"); break;
8561 case DVD_AUD_EXT_DirectorComments2: str += _T(" (Director Comments 2)"); break;
8564 CString format;
8565 switch(ATR.AudioFormat)
8567 case DVD_AudioFormat_AC3: format = _T("AC3"); break;
8568 case DVD_AudioFormat_MPEG1:
8569 case DVD_AudioFormat_MPEG1_DRC: format = _T("MPEG1"); break;
8570 case DVD_AudioFormat_MPEG2:
8571 case DVD_AudioFormat_MPEG2_DRC: format = _T("MPEG2"); break;
8572 case DVD_AudioFormat_LPCM: format = _T("LPCM"); break;
8573 case DVD_AudioFormat_DTS: format = _T("DTS"); break;
8574 case DVD_AudioFormat_SDDS: format = _T("SDDS"); break;
8577 if(!format.IsEmpty())
8579 str.Format(_T("%s, %s %dHz %dbits %d channel(s)"),
8580 CString(str),
8581 format,
8582 ATR.dwFrequency,
8583 ATR.bQuantization,
8584 ATR.bNumberOfChannels);
8588 str.Replace(_T("&"), _T("&&"));
8590 pSub->AppendMenu(flags, id++, str);
8595 void CMainFrame::SetupNavSubtitleSubMenu()
8597 CMenu* pSub = &m_navsubtitle;
8599 if(!IsMenu(pSub->m_hMenu)) pSub->CreatePopupMenu();
8600 else while(pSub->RemoveMenu(0, MF_BYPOSITION));
8602 if(m_iMediaLoadState != MLS_LOADED) return;
8604 UINT id = ID_NAVIGATE_SUBP_SUBITEM_START;
8606 if(m_iPlaybackMode == PM_FILE)
8608 SetupNavStreamSelectSubMenu(pSub, id, 2);
8610 else if(m_iPlaybackMode == PM_DVD)
8612 ULONG ulStreamsAvailable, ulCurrentStream;
8613 BOOL bIsDisabled;
8614 if(FAILED(pDVDI->GetCurrentSubpicture(&ulStreamsAvailable, &ulCurrentStream, &bIsDisabled))
8615 || ulStreamsAvailable == 0)
8616 return;
8618 LCID DefLanguage;
8619 DVD_SUBPICTURE_LANG_EXT ext;
8620 if(FAILED(pDVDI->GetDefaultSubpictureLanguage(&DefLanguage, &ext)))
8621 return;
8623 pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|(bIsDisabled?0:MF_CHECKED), id++, _T("Enabled"));
8624 pSub->AppendMenu(MF_BYCOMMAND|MF_SEPARATOR|MF_ENABLED);
8626 for(ULONG i = 0; i < ulStreamsAvailable; i++)
8628 LCID Language;
8629 if(FAILED(pDVDI->GetSubpictureLanguage(i, &Language)))
8630 continue;
8632 UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
8633 if(Language == DefLanguage) flags |= MF_DEFAULT;
8634 if(i == ulCurrentStream) flags |= MF_CHECKED;
8636 CString str(_T("Unknown"));
8637 if(Language)
8639 int len = GetLocaleInfo(Language, LOCALE_SENGLANGUAGE, str.GetBuffer(256), 256);
8640 str.ReleaseBufferSetLength(max(len-1, 0));
8643 DVD_SubpictureAttributes ATR;
8644 if(SUCCEEDED(pDVDI->GetSubpictureAttributes(i, &ATR)))
8646 switch(ATR.LanguageExtension)
8648 case DVD_SP_EXT_NotSpecified:
8649 default: break;
8650 case DVD_SP_EXT_Caption_Normal: str += _T(""); break;
8651 case DVD_SP_EXT_Caption_Big: str += _T(" (Big)"); break;
8652 case DVD_SP_EXT_Caption_Children: str += _T(" (Children)"); break;
8653 case DVD_SP_EXT_CC_Normal: str += _T(" (CC)"); break;
8654 case DVD_SP_EXT_CC_Big: str += _T(" (CC Big)"); break;
8655 case DVD_SP_EXT_CC_Children: str += _T(" (CC Children)"); break;
8656 case DVD_SP_EXT_Forced: str += _T(" (Forced)"); break;
8657 case DVD_SP_EXT_DirectorComments_Normal: str += _T(" (Director Comments)"); break;
8658 case DVD_SP_EXT_DirectorComments_Big: str += _T(" (Director Comments, Big)"); break;
8659 case DVD_SP_EXT_DirectorComments_Children: str += _T(" (Director Comments, Children)"); break;
8663 str.Replace(_T("&"), _T("&&"));
8665 pSub->AppendMenu(flags, id++, str);
8670 void CMainFrame::SetupNavAngleSubMenu()
8672 CMenu* pSub = &m_navangle;
8674 if(!IsMenu(pSub->m_hMenu)) pSub->CreatePopupMenu();
8675 else while(pSub->RemoveMenu(0, MF_BYPOSITION));
8677 if(m_iMediaLoadState != MLS_LOADED) return;
8679 UINT id = ID_NAVIGATE_ANGLE_SUBITEM_START;
8681 if(m_iPlaybackMode == PM_FILE)
8683 SetupNavStreamSelectSubMenu(pSub, id, 0);
8685 else if(m_iPlaybackMode == PM_DVD)
8687 ULONG ulStreamsAvailable, ulCurrentStream;
8688 if(FAILED(pDVDI->GetCurrentAngle(&ulStreamsAvailable, &ulCurrentStream)))
8689 return;
8691 if(ulStreamsAvailable < 2) return; // one choice is not a choice...
8693 for(ULONG i = 1; i <= ulStreamsAvailable; i++)
8695 UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
8696 if(i == ulCurrentStream) flags |= MF_CHECKED;
8698 CString str;
8699 str.Format(_T("Angle %d"), i);
8701 pSub->AppendMenu(flags, id++, str);
8706 void CMainFrame::SetupNavChaptersSubMenu()
8708 CMenu* pSub = &m_navchapters;
8710 if(!IsMenu(pSub->m_hMenu)) pSub->CreatePopupMenu();
8711 else while(pSub->RemoveMenu(0, MF_BYPOSITION));
8713 if(m_iMediaLoadState != MLS_LOADED)
8714 return;
8716 UINT id = ID_NAVIGATE_CHAP_SUBITEM_START;
8718 if(m_iPlaybackMode == PM_FILE)
8720 SetupChapters();
8722 REFERENCE_TIME rt = GetPos();
8723 DWORD j = m_pCB->ChapLookup(&rt, NULL);
8725 for(DWORD i = 0; i < m_pCB->ChapGetCount(); i++, id++)
8727 rt = 0;
8728 CComBSTR bstr;
8729 if(FAILED(m_pCB->ChapGet(i, &rt, &bstr)))
8730 continue;
8732 int s = (int)((rt/10000000)%60);
8733 int m = (int)((rt/10000000/60)%60);
8734 int h = (int)((rt/10000000/60/60));
8736 CString time;
8737 time.Format(_T("[%02d:%02d:%02d] "), h, m, s);
8739 CString name = CString(bstr);
8740 name.Replace(_T("&"), _T("&&"));
8741 name.Replace(_T("\t"), _T(" "));
8743 UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
8744 if(i == j) flags |= MF_CHECKED;
8745 if(id != ID_NAVIGATE_CHAP_SUBITEM_START && i == 0) pSub->AppendMenu(MF_SEPARATOR);
8746 pSub->AppendMenu(flags, id, name + '\t' + time);
8749 if(m_wndPlaylistBar.GetCount() > 1)
8751 POSITION pos = m_wndPlaylistBar.m_pl.GetHeadPosition();
8752 while(pos)
8754 UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
8755 if(pos == m_wndPlaylistBar.m_pl.GetPos()) flags |= MF_CHECKED;
8756 if(id != ID_NAVIGATE_CHAP_SUBITEM_START && pos == m_wndPlaylistBar.m_pl.GetHeadPosition())
8757 pSub->AppendMenu(MF_SEPARATOR);
8758 CPlaylistItem& pli = m_wndPlaylistBar.m_pl.GetNext(pos);
8759 CString name = pli.GetLabel();
8760 name.Replace(_T("&"), _T("&&"));
8761 pSub->AppendMenu(flags, id++, name);
8765 else if(m_iPlaybackMode == PM_DVD)
8767 ULONG ulNumOfVolumes, ulVolume;
8768 DVD_DISC_SIDE Side;
8769 ULONG ulNumOfTitles = 0;
8770 pDVDI->GetDVDVolumeInfo(&ulNumOfVolumes, &ulVolume, &Side, &ulNumOfTitles);
8772 DVD_PLAYBACK_LOCATION2 Location;
8773 pDVDI->GetCurrentLocation(&Location);
8775 ULONG ulNumOfChapters = 0;
8776 pDVDI->GetNumberOfChapters(Location.TitleNum, &ulNumOfChapters);
8778 ULONG ulUOPs = 0;
8779 pDVDI->GetCurrentUOPS(&ulUOPs);
8781 for(ULONG i = 1; i <= ulNumOfTitles; i++)
8783 UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
8784 if(i == Location.TitleNum) flags |= MF_CHECKED;
8785 if(ulUOPs&UOP_FLAG_Play_Title) flags |= MF_DISABLED|MF_GRAYED;
8787 CString str;
8788 str.Format(_T("Title %d"), i);
8790 pSub->AppendMenu(flags, id++, str);
8793 for(ULONG i = 1; i <= ulNumOfChapters; i++)
8795 UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
8796 if(i == Location.ChapterNum) flags |= MF_CHECKED;
8797 if(ulUOPs&UOP_FLAG_Play_Chapter) flags |= MF_DISABLED|MF_GRAYED;
8798 if(i == 1) flags |= MF_MENUBARBREAK;
8800 CString str;
8801 str.Format(_T("Chapter %d"), i);
8803 pSub->AppendMenu(flags, id++, str);
8808 void CMainFrame::SetupNavStreamSelectSubMenu(CMenu* pSub, UINT id, DWORD dwSelGroup)
8810 UINT baseid = id;
8812 CComQIPtr<IAMStreamSelect> pSS = FindFilter(CLSID_OggSplitter, pGB);
8813 if(!pSS) pSS = FindFilter(L"{55DA30FC-F16B-49fc-BAA5-AE59FC65F82D}", pGB);
8814 if(!pSS) return;
8816 DWORD cStreams;
8817 if(FAILED(pSS->Count(&cStreams)))
8818 return;
8820 DWORD dwPrevGroup = -1;
8822 for(int i = 0, j = cStreams; i < j; i++)
8824 DWORD dwFlags, dwGroup;
8825 LCID lcid;
8826 WCHAR* pszName = NULL;
8828 if(FAILED(pSS->Info(i, NULL, &dwFlags, &lcid, &dwGroup, &pszName, NULL, NULL))
8829 || !pszName)
8830 continue;
8832 CString name(pszName);
8833 CString lcname = CString(name).MakeLower();
8835 if(pszName) CoTaskMemFree(pszName);
8837 if(dwGroup != dwSelGroup)
8838 continue;
8840 if(dwPrevGroup != -1 && dwPrevGroup != dwGroup)
8841 pSub->AppendMenu(MF_SEPARATOR);
8842 dwPrevGroup = dwGroup;
8844 CString str;
8846 if(lcname.Find(_T(" off")) >= 0)
8848 str = _T("Disabled");
8850 else
8852 if(lcid == 0)
8854 str.Format(_T("Unknown %d"), id - baseid);
8856 else
8858 int len = GetLocaleInfo(lcid, LOCALE_SENGLANGUAGE, str.GetBuffer(64), 64);
8859 str.ReleaseBufferSetLength(max(len-1, 0));
8862 CString lcstr = CString(str).MakeLower();
8864 if(str.IsEmpty() || lcname.Find(lcstr) >= 0) str = name;
8865 else if(!name.IsEmpty()) str = CString(name) + _T(" (") + str + _T(")");
8868 UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
8869 if(dwFlags) flags |= MF_CHECKED;
8871 str.Replace(_T("&"), _T("&&"));
8872 pSub->AppendMenu(flags, id++, str);
8876 void CMainFrame::OnNavStreamSelectSubMenu(UINT id, DWORD dwSelGroup)
8878 CComQIPtr<IAMStreamSelect> pSS = FindFilter(CLSID_OggSplitter, pGB);
8879 if(!pSS) pSS = FindFilter(L"{55DA30FC-F16B-49fc-BAA5-AE59FC65F82D}", pGB);
8880 if(!pSS) return;
8882 DWORD cStreams;
8883 if(FAILED(pSS->Count(&cStreams)))
8884 return;
8886 for(int i = 0, j = cStreams; i < j; i++)
8888 DWORD dwFlags, dwGroup;
8889 LCID lcid;
8890 WCHAR* pszName = NULL;
8892 if(FAILED(pSS->Info(i, NULL, &dwFlags, &lcid, &dwGroup, &pszName, NULL, NULL))
8893 || !pszName)
8894 continue;
8896 if(pszName) CoTaskMemFree(pszName);
8898 if(dwGroup != dwSelGroup)
8899 continue;
8901 if(id == 0)
8903 pSS->Enable(i, AMSTREAMSELECTENABLE_ENABLE);
8904 break;
8907 id--;
8911 void CMainFrame::SetupFavoritesSubMenu()
8913 CMenu* pSub = &m_favorites;
8915 if(!IsMenu(pSub->m_hMenu)) pSub->CreatePopupMenu();
8916 else while(pSub->RemoveMenu(0, MF_BYPOSITION));
8918 AppSettings& s = AfxGetAppSettings();
8920 pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, ID_FAVORITES_ADD, ResStr(IDS_FAVORITES_ADD));
8921 pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, ID_FAVORITES_ORGANIZE, ResStr(IDS_FAVORITES_ORGANIZE));
8923 int nLastGroupStart = pSub->GetMenuItemCount();
8925 UINT id = ID_FAVORITES_FILE_START;
8927 CAtlList<CString> sl;
8928 AfxGetAppSettings().GetFav(FAV_FILE, sl);
8930 POSITION pos = sl.GetHeadPosition();
8931 while(pos)
8933 UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
8935 CString str = sl.GetNext(pos);
8936 str.Replace(_T("&"), _T("&&"));
8937 str.Replace(_T("\t"), _T(" "));
8939 CAtlList<CString> sl;
8940 Explode(str, sl, ';', 2);
8942 str = sl.RemoveHead();
8944 if(!sl.IsEmpty())
8946 REFERENCE_TIME rt = 0;
8947 if(1 == _stscanf(sl.GetHead(), _T("%I64d"), &rt) && rt > 0)
8949 DVD_HMSF_TIMECODE hmsf = RT2HMSF(rt, 0);
8950 str.Format(_T("%s\t[%02d:%02d:%02d]"), CString(str), hmsf.bHours, hmsf.bMinutes, hmsf.bSeconds);
8954 if(!str.IsEmpty())
8955 pSub->AppendMenu(flags, id, str);
8957 id++;
8960 if(id > ID_FAVORITES_FILE_START)
8961 pSub->InsertMenu(nLastGroupStart, MF_SEPARATOR|MF_ENABLED|MF_BYPOSITION);
8963 nLastGroupStart = pSub->GetMenuItemCount();
8965 id = ID_FAVORITES_DVD_START;
8967 AfxGetAppSettings().GetFav(FAV_DVD, sl);
8969 pos = sl.GetHeadPosition();
8970 while(pos)
8972 UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
8974 CString str = sl.GetNext(pos);
8975 str.Replace(_T("&"), _T("&&"));
8977 CAtlList<CString> sl;
8978 Explode(str, sl, ';', 2);
8980 str = sl.RemoveHead();
8982 if(!sl.IsEmpty())
8984 // TODO
8987 if(!str.IsEmpty())
8988 pSub->AppendMenu(flags, id, str);
8990 id++;
8993 if(id > ID_FAVORITES_DVD_START)
8994 pSub->InsertMenu(nLastGroupStart, MF_SEPARATOR|MF_ENABLED|MF_BYPOSITION);
8996 nLastGroupStart = pSub->GetMenuItemCount();
8998 id = ID_FAVORITES_DEVICE_START;
9000 AfxGetAppSettings().GetFav(FAV_DEVICE, sl);
9002 pos = sl.GetHeadPosition();
9003 while(pos)
9005 UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
9007 CString str = sl.GetNext(pos);
9008 str.Replace(_T("&"), _T("&&"));
9010 CAtlList<CString> sl;
9011 Explode(str, sl, ';', 2);
9013 str = sl.RemoveHead();
9015 if(!str.IsEmpty())
9016 pSub->AppendMenu(flags, id, str);
9018 id++;
9022 void CMainFrame::SetupShadersSubMenu()
9024 CMenu* pSub = &m_shaders;
9026 if(!IsMenu(pSub->m_hMenu)) pSub->CreatePopupMenu();
9027 else while(pSub->RemoveMenu(0, MF_BYPOSITION));
9029 CWinApp* pApp = AfxGetApp();
9031 pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, ID_SHADERS_START, ResStr(IDS_SHADER_OFF));
9033 UINT id = ID_SHADERS_START+1;
9035 if(POSITION pos = AfxGetAppSettings().m_shaders.GetHeadPosition())
9037 pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, ResStr(IDS_SHADER_COMBINE));
9038 pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, ResStr(IDS_SHADER_EDIT));
9039 pSub->AppendMenu(MF_SEPARATOR);
9041 MENUITEMINFO mii;
9042 memset(&mii, 0, sizeof(mii));
9043 mii.cbSize = sizeof(mii);
9044 mii.fMask |= MIIM_DATA;
9046 while(pos)
9048 const AppSettings::Shader& s = AfxGetAppSettings().m_shaders.GetNext(pos);
9049 CString label = s.label;
9050 label.Replace(_T("&"), _T("&&"));
9051 pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id, label);
9052 mii.dwItemData = (ULONG_PTR)&s;
9053 pSub->SetMenuItemInfo(id, &mii);
9054 id++;
9059 /////////////
9061 void CMainFrame::ShowControls(int nCS, bool fSave)
9063 int nCSprev = AfxGetAppSettings().nCS;
9064 int hbefore = 0, hafter = 0;
9066 m_pLastBar = NULL;
9068 POSITION pos = m_bars.GetHeadPosition();
9069 for(int i = 1; pos; i <<= 1)
9071 CControlBar* pNext = m_bars.GetNext(pos);
9072 ShowControlBar(pNext, !!(nCS&i), TRUE);
9073 if(nCS&i) m_pLastBar = pNext;
9075 CSize s = pNext->CalcFixedLayout(FALSE, TRUE);
9076 if(nCSprev&i) hbefore += s.cy;
9077 if(nCS&i) hafter += s.cy;
9080 WINDOWPLACEMENT wp;
9081 wp.length = sizeof(wp);
9082 GetWindowPlacement(&wp);
9084 if(wp.showCmd != SW_SHOWMAXIMIZED && !m_fFullScreen)
9086 CRect r;
9087 GetWindowRect(r);
9088 MoveWindow(r.left, r.top, r.Width(), r.Height()+(hafter-hbefore));
9091 if(fSave)
9092 AfxGetAppSettings().nCS = nCS;
9094 RecalcLayout();
9097 void CMainFrame::SetAlwaysOnTop(int i)
9099 AfxGetAppSettings().iOnTop = i;
9101 if(!m_fFullScreen)
9103 const CWnd* pInsertAfter = NULL;
9105 if(i == 0)
9106 pInsertAfter = &wndNoTopMost;
9107 else if(i == 1)
9108 pInsertAfter = &wndTopMost;
9109 else // if(i == 2)
9110 pInsertAfter = GetMediaState() == State_Running ? &wndTopMost : &wndNoTopMost;
9112 SetWindowPos(pInsertAfter, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
9114 else if(!(GetWindowLong(m_hWnd, GWL_EXSTYLE)&WS_EX_TOPMOST))
9116 SetWindowPos(&wndTopMost, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
9120 void CMainFrame::AddTextPassThruFilter()
9122 BeginEnumFilters(pGB, pEF, pBF)
9124 if(!IsSplitter(pBF)) continue;
9126 BeginEnumPins(pBF, pEP, pPin)
9128 CComPtr<IPin> pPinTo;
9129 AM_MEDIA_TYPE mt;
9130 if(FAILED(pPin->ConnectedTo(&pPinTo)) || !pPinTo
9131 || FAILED(pPin->ConnectionMediaType(&mt))
9132 || mt.majortype != MEDIATYPE_Text && mt.majortype != MEDIATYPE_Subtitle)
9133 continue;
9135 CComQIPtr<IBaseFilter> pTPTF = new CTextPassThruFilter(this);
9136 CStringW name;
9137 name.Format(L"TextPassThru%08x", pTPTF);
9138 if(FAILED(pGB->AddFilter(pTPTF, name)))
9139 continue;
9141 HRESULT hr;
9143 hr = pPinTo->Disconnect();
9144 hr = pPin->Disconnect();
9146 if(FAILED(hr = pGB->ConnectDirect(pPin, GetFirstPin(pTPTF, PINDIR_INPUT), NULL))
9147 || FAILED(hr = pGB->ConnectDirect(GetFirstPin(pTPTF, PINDIR_OUTPUT), pPinTo, NULL)))
9148 hr = pGB->ConnectDirect(pPin, pPinTo, NULL);
9149 else
9150 m_pSubStreams.AddTail(CComQIPtr<ISubStream>(pTPTF));
9152 EndEnumPins
9154 EndEnumFilters
9157 bool CMainFrame::LoadSubtitle(CString fn)
9159 CComPtr<ISubStream> pSubStream;
9161 // TMP: maybe this will catch something for those who get a runtime error dialog when opening subtitles from cds
9164 if(!pSubStream)
9166 CAutoPtr<CVobSubFile> p(new CVobSubFile(&m_csSubLock));
9167 if(CString(CPath(fn).GetExtension()).MakeLower() == _T(".idx") && p && p->Open(fn) && p->GetStreamCount() > 0)
9168 pSubStream = p.Detach();
9171 if(!pSubStream)
9173 CAutoPtr<ssf::CRenderer> p(new ssf::CRenderer(&m_csSubLock));
9174 if(p && p->Open(fn) && p->GetStreamCount() > 0)
9175 pSubStream = p.Detach();
9178 if(!pSubStream)
9180 CAutoPtr<CRenderedTextSubtitle> p(new CRenderedTextSubtitle(&m_csSubLock));
9181 if(p && p->Open(fn, DEFAULT_CHARSET) && p->GetStreamCount() > 0)
9182 pSubStream = p.Detach();
9185 catch(CException* e)
9187 e->Delete();
9190 if(pSubStream)
9192 m_pSubStreams.AddTail(pSubStream);
9195 return(!!pSubStream);
9198 void CMainFrame::UpdateSubtitle(bool fApplyDefStyle)
9200 if(!m_pCAP) return;
9202 int i = m_iSubtitleSel;
9204 POSITION pos = m_pSubStreams.GetHeadPosition();
9205 while(pos && i >= 0)
9207 CComPtr<ISubStream> pSubStream = m_pSubStreams.GetNext(pos);
9209 if(i < pSubStream->GetStreamCount())
9211 CAutoLock cAutoLock(&m_csSubLock);
9212 pSubStream->SetStream(i);
9213 SetSubtitle(pSubStream, fApplyDefStyle);
9214 return;
9217 i -= pSubStream->GetStreamCount();
9220 m_pCAP->SetSubPicProvider(NULL);
9223 void CMainFrame::SetSubtitle(ISubStream* pSubStream, bool fApplyDefStyle)
9225 AppSettings& s = AfxGetAppSettings();
9227 if(pSubStream)
9229 CLSID clsid;
9230 pSubStream->GetClassID(&clsid);
9232 if(clsid == __uuidof(CVobSubFile))
9234 CVobSubFile* pVSF = (CVobSubFile*)(ISubStream*)pSubStream;
9236 if(fApplyDefStyle)
9238 pVSF->SetAlignment(s.fOverridePlacement, s.nHorPos, s.nVerPos, 1, 1);
9241 else if(clsid == __uuidof(CVobSubStream))
9243 CVobSubStream* pVSS = (CVobSubStream*)(ISubStream*)pSubStream;
9245 if(fApplyDefStyle)
9247 pVSS->SetAlignment(s.fOverridePlacement, s.nHorPos, s.nVerPos, 1, 1);
9250 else if(clsid == __uuidof(CRenderedTextSubtitle))
9252 CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)pSubStream;
9254 STSStyle style;
9256 if(fApplyDefStyle || pRTS->m_fUsingAutoGeneratedDefaultStyle)
9258 style = s.subdefstyle;
9260 if(s.fOverridePlacement)
9262 style.scrAlignment = 2;
9263 int w = pRTS->m_dstScreenSize.cx;
9264 int h = pRTS->m_dstScreenSize.cy;
9265 int mw = w - style.marginRect.left - style.marginRect.right;
9266 style.marginRect.bottom = h - MulDiv(h, s.nVerPos, 100);
9267 style.marginRect.left = MulDiv(w, s.nHorPos, 100) - mw/2;
9268 style.marginRect.right = w - (style.marginRect.left + mw);
9271 pRTS->SetDefaultStyle(style);
9274 if(pRTS->GetDefaultStyle(style) && style.relativeTo == 2)
9276 style.relativeTo = s.subdefstyle.relativeTo;
9277 pRTS->SetDefaultStyle(style);
9280 pRTS->Deinit();
9284 if(!fApplyDefStyle)
9286 m_iSubtitleSel = -1;
9288 if(pSubStream)
9291 int i = 0;
9293 POSITION pos = m_pSubStreams.GetHeadPosition();
9294 while(pos)
9296 CComPtr<ISubStream> pSubStream2 = m_pSubStreams.GetNext(pos);
9298 if(pSubStream == pSubStream2)
9300 m_iSubtitleSel = i + pSubStream2->GetStream();
9301 break;
9304 i += pSubStream2->GetStreamCount();
9310 m_nSubtitleId = (DWORD_PTR)pSubStream;
9312 if(m_pCAP)
9314 m_pCAP->SetSubPicProvider(CComQIPtr<ISubPicProvider>(pSubStream));
9315 m_wndSubresyncBar.SetSubtitle(pSubStream, m_pCAP->GetFPS());
9319 void CMainFrame::ReplaceSubtitle(ISubStream* pSubStreamOld, ISubStream* pSubStreamNew)
9321 POSITION pos = m_pSubStreams.GetHeadPosition();
9322 while(pos)
9324 POSITION cur = pos;
9325 if(pSubStreamOld == m_pSubStreams.GetNext(pos))
9327 m_pSubStreams.SetAt(cur, pSubStreamNew);
9328 UpdateSubtitle();
9329 break;
9334 void CMainFrame::InvalidateSubtitle(DWORD_PTR nSubtitleId, REFERENCE_TIME rtInvalidate)
9336 if(m_pCAP)
9338 if(nSubtitleId == -1 || nSubtitleId == m_nSubtitleId)
9339 m_pCAP->Invalidate(rtInvalidate);
9343 void CMainFrame::ReloadSubtitle()
9345 POSITION pos = m_pSubStreams.GetHeadPosition();
9346 while(pos) m_pSubStreams.GetNext(pos)->Reload();
9347 UpdateSubtitle();
9350 REFERENCE_TIME CMainFrame::GetPos()
9352 return(m_iMediaLoadState == MLS_LOADED ? m_wndSeekBar.GetPos() : 0);
9355 REFERENCE_TIME CMainFrame::GetDur()
9357 __int64 start, stop;
9358 m_wndSeekBar.GetRange(start, stop);
9359 return(m_iMediaLoadState == MLS_LOADED ? stop : 0);
9362 void CMainFrame::SeekTo(REFERENCE_TIME rtPos, bool fSeekToKeyFrame)
9364 OAFilterState fs = GetMediaState();
9366 if(rtPos < 0) rtPos = 0;
9368 if(m_iPlaybackMode == PM_FILE)
9370 if(fs == State_Stopped)
9371 SendMessage(WM_COMMAND, ID_PLAY_PAUSE);
9373 HRESULT hr;
9375 if(fSeekToKeyFrame)
9377 if(!m_kfs.IsEmpty())
9379 int i = rangebsearch(rtPos, m_kfs);
9380 if(i >= 0 && i < m_kfs.GetCount())
9381 rtPos = m_kfs[i];
9385 hr = pMS->SetPositions(&rtPos, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning);
9387 else if(m_iPlaybackMode == PM_DVD && m_iDVDDomain == DVD_DOMAIN_Title)
9389 if(fs != State_Running)
9390 SendMessage(WM_COMMAND, ID_PLAY_PLAY);
9392 DVD_HMSF_TIMECODE tc = RT2HMSF(rtPos);
9393 pDVDC->PlayAtTime(&tc, DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
9395 // if(fs != State_Running)
9396 // SendMessage(WM_COMMAND, ID_PLAY_PAUSE);
9398 else if(m_iPlaybackMode == PM_CAPTURE)
9400 TRACE(_T("Warning (CMainFrame::SeekTo): Trying to seek in capture mode"));
9403 m_fEndOfStream = false;
9406 void CMainFrame::CleanGraph()
9408 if(!pGB) return;
9410 BeginEnumFilters(pGB, pEF, pBF)
9412 CComQIPtr<IAMFilterMiscFlags> pAMMF(pBF);
9413 if(pAMMF && (pAMMF->GetMiscFlags()&AM_FILTER_MISC_FLAGS_IS_SOURCE))
9414 continue;
9416 // some capture filters forget to set AM_FILTER_MISC_FLAGS_IS_SOURCE
9417 // or to implement the IAMFilterMiscFlags interface
9418 if(pBF == pVidCap || pBF == pAudCap)
9419 continue;
9421 if(CComQIPtr<IFileSourceFilter>(pBF))
9422 continue;
9424 int nIn, nOut, nInC, nOutC;
9425 if(CountPins(pBF, nIn, nOut, nInC, nOutC) > 0 && (nInC+nOutC) == 0)
9427 TRACE(CStringW(L"Removing: ") + GetFilterName(pBF) + '\n');
9429 pGB->RemoveFilter(pBF);
9430 pEF->Reset();
9433 EndEnumFilters
9436 #define AUDIOBUFFERLEN 500
9438 static void SetLatency(IBaseFilter* pBF, int cbBuffer)
9440 BeginEnumPins(pBF, pEP, pPin)
9442 if(CComQIPtr<IAMBufferNegotiation> pAMBN = pPin)
9444 ALLOCATOR_PROPERTIES ap;
9445 ap.cbAlign = -1; // -1 means no preference.
9446 ap.cbBuffer = cbBuffer;
9447 ap.cbPrefix = -1;
9448 ap.cBuffers = -1;
9449 pAMBN->SuggestAllocatorProperties(&ap);
9452 EndEnumPins
9455 HRESULT CMainFrame::BuildCapture(IPin* pPin, IBaseFilter* pBF[3], const GUID& majortype, AM_MEDIA_TYPE* pmt)
9457 IBaseFilter* pBuff = pBF[0];
9458 IBaseFilter* pEnc = pBF[1];
9459 IBaseFilter* pMux = pBF[2];
9461 if(!pPin || !pMux) return E_FAIL;
9463 CString err;
9465 HRESULT hr = S_OK;
9467 CFilterInfo fi;
9468 if(FAILED(pMux->QueryFilterInfo(&fi)) || !fi.pGraph)
9469 pGB->AddFilter(pMux, L"Multiplexer");
9471 CStringW prefix, prefixl;
9472 if(majortype == MEDIATYPE_Video) prefix = L"Video ";
9473 else if(majortype == MEDIATYPE_Audio) prefix = L"Audio ";
9474 prefixl = prefix;
9475 prefixl.MakeLower();
9477 if(pBuff)
9479 hr = pGB->AddFilter(pBuff, prefix + L"Buffer");
9480 if(FAILED(hr))
9482 err = _T("Can't add ") + CString(prefixl) + _T("buffer filter");
9483 AfxMessageBox(err);
9484 return hr;
9487 hr = pGB->ConnectFilter(pPin, pBuff);
9488 if(FAILED(hr))
9490 err = _T("Error connecting the ") + CString(prefixl) + _T("buffer filter");
9491 AfxMessageBox(err);
9492 return(hr);
9495 pPin = GetFirstPin(pBuff, PINDIR_OUTPUT);
9498 if(pEnc)
9500 hr = pGB->AddFilter(pEnc, prefix + L"Encoder");
9501 if(FAILED(hr))
9503 err = _T("Can't add ") + CString(prefixl) + _T("encoder filter");
9504 AfxMessageBox(err);
9505 return hr;
9508 hr = pGB->ConnectFilter(pPin, pEnc);
9509 if(FAILED(hr))
9511 err = _T("Error connecting the ") + CString(prefixl) + _T("encoder filter");
9512 AfxMessageBox(err);
9513 return(hr);
9516 pPin = GetFirstPin(pEnc, PINDIR_OUTPUT);
9518 if(CComQIPtr<IAMStreamConfig> pAMSC = pPin)
9520 if(pmt->majortype == majortype)
9522 hr = pAMSC->SetFormat(pmt);
9523 if(FAILED(hr))
9525 err = _T("Can't set compression format on the ") + CString(prefixl) + _T("encoder filter");
9526 AfxMessageBox(err);
9527 return(hr);
9534 // if(pMux)
9536 hr = pGB->ConnectFilter(pPin, pMux);
9537 if(FAILED(hr))
9539 err = _T("Error connecting ") + CString(prefixl) + _T(" to the muliplexer filter");
9540 AfxMessageBox(err);
9541 return(hr);
9545 CleanGraph();
9547 return S_OK;
9550 bool CMainFrame::BuildToCapturePreviewPin(
9551 IBaseFilter* pVidCap, IPin** ppVidCapPin, IPin** ppVidPrevPin,
9552 IBaseFilter* pAudCap, IPin** ppAudCapPin, IPin** ppAudPrevPin)
9554 HRESULT hr;
9556 *ppVidCapPin = *ppVidPrevPin = NULL;
9557 *ppAudCapPin = *ppAudPrevPin = NULL;
9559 CComPtr<IPin> pDVAudPin;
9561 if(pVidCap)
9563 CComPtr<IPin> pPin;
9564 if(!pAudCap // only look for interleaved stream when we don't use any other audio capture source
9565 && SUCCEEDED(pCGB->FindPin(pVidCap, PINDIR_OUTPUT, &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Interleaved, TRUE, 0, &pPin)))
9567 CComPtr<IBaseFilter> pDVSplitter;
9568 hr = pDVSplitter.CoCreateInstance(CLSID_DVSplitter);
9569 hr = pGB->AddFilter(pDVSplitter, L"DV Splitter");
9571 hr = pCGB->RenderStream(NULL, &MEDIATYPE_Interleaved, pPin, NULL, pDVSplitter);
9573 pPin = NULL;
9574 hr = pCGB->FindPin(pDVSplitter, PINDIR_OUTPUT, NULL, &MEDIATYPE_Video, TRUE, 0, &pPin);
9575 hr = pCGB->FindPin(pDVSplitter, PINDIR_OUTPUT, NULL, &MEDIATYPE_Audio, TRUE, 0, &pDVAudPin);
9577 CComPtr<IBaseFilter> pDVDec;
9578 hr = pDVDec.CoCreateInstance(CLSID_DVVideoCodec);
9579 hr = pGB->AddFilter(pDVDec, L"DV Video Decoder");
9581 hr = pGB->ConnectFilter(pPin, pDVDec);
9583 pPin = NULL;
9584 hr = pCGB->FindPin(pDVDec, PINDIR_OUTPUT, NULL, &MEDIATYPE_Video, TRUE, 0, &pPin);
9586 else if(SUCCEEDED(pCGB->FindPin(pVidCap, PINDIR_OUTPUT, &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, TRUE, 0, &pPin)))
9589 else
9591 AfxMessageBox(_T("No video capture pin was found"));
9592 return(false);
9595 CComPtr<IBaseFilter> pSmartTee;
9596 hr = pSmartTee.CoCreateInstance(CLSID_SmartTee);
9597 hr = pGB->AddFilter(pSmartTee, L"Smart Tee (video)");
9599 hr = pGB->ConnectFilter(pPin, pSmartTee);
9601 hr = pSmartTee->FindPin(L"Preview", ppVidPrevPin);
9602 hr = pSmartTee->FindPin(L"Capture", ppVidCapPin);
9605 if(pAudCap || pDVAudPin)
9607 CComPtr<IPin> pPin;
9608 if(pDVAudPin)
9610 pPin = pDVAudPin;
9612 else if(SUCCEEDED(pCGB->FindPin(pAudCap, PINDIR_OUTPUT, &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, TRUE, 0, &pPin)))
9615 else
9617 AfxMessageBox(_T("No audio capture pin was found"));
9618 return(false);
9621 CComPtr<IBaseFilter> pSmartTee;
9622 hr = pSmartTee.CoCreateInstance(CLSID_SmartTee);
9623 hr = pGB->AddFilter(pSmartTee, L"Smart Tee (audio)");
9625 hr = pGB->ConnectFilter(pPin, pSmartTee);
9627 hr = pSmartTee->FindPin(L"Preview", ppAudPrevPin);
9628 hr = pSmartTee->FindPin(L"Capture", ppAudCapPin);
9631 return(true);
9634 bool CMainFrame::BuildGraphVideoAudio(int fVPreview, bool fVCapture, int fAPreview, bool fACapture)
9636 if(!pCGB) return(false);
9638 SaveMediaState;
9640 HRESULT hr;
9642 pGB->NukeDownstream(pVidCap);
9643 pGB->NukeDownstream(pAudCap);
9645 CleanGraph();
9647 if(pAMVSCCap) hr = pAMVSCCap->SetFormat(&m_wndCaptureBar.m_capdlg.m_mtv);
9648 if(pAMVSCPrev) hr = pAMVSCPrev->SetFormat(&m_wndCaptureBar.m_capdlg.m_mtv);
9649 if(pAMASC) hr = pAMASC->SetFormat(&m_wndCaptureBar.m_capdlg.m_mta);
9651 CComPtr<IBaseFilter> pVidBuffer = m_wndCaptureBar.m_capdlg.m_pVidBuffer;
9652 CComPtr<IBaseFilter> pAudBuffer = m_wndCaptureBar.m_capdlg.m_pAudBuffer;
9653 CComPtr<IBaseFilter> pVidEnc = m_wndCaptureBar.m_capdlg.m_pVidEnc;
9654 CComPtr<IBaseFilter> pAudEnc = m_wndCaptureBar.m_capdlg.m_pAudEnc;
9655 CComPtr<IBaseFilter> pMux = m_wndCaptureBar.m_capdlg.m_pMux;
9656 CComPtr<IBaseFilter> pDst = m_wndCaptureBar.m_capdlg.m_pDst;
9657 CComPtr<IBaseFilter> pAudMux = m_wndCaptureBar.m_capdlg.m_pAudMux;
9658 CComPtr<IBaseFilter> pAudDst = m_wndCaptureBar.m_capdlg.m_pAudDst;
9660 bool fFileOutput = (pMux && pDst) || (pAudMux && pAudDst);
9661 bool fCapture = (fVCapture || fACapture);
9663 if(pAudCap)
9665 AM_MEDIA_TYPE* pmt = &m_wndCaptureBar.m_capdlg.m_mta;
9666 int ms = (fACapture && fFileOutput && m_wndCaptureBar.m_capdlg.m_fAudOutput) ? AUDIOBUFFERLEN : 60;
9667 if(pMux != pAudMux && fACapture) SetLatency(pAudCap, -1);
9668 else if(pmt->pbFormat) SetLatency(pAudCap, ((WAVEFORMATEX*)pmt->pbFormat)->nAvgBytesPerSec * ms / 1000);
9671 CComPtr<IPin> pVidCapPin, pVidPrevPin, pAudCapPin, pAudPrevPin;
9672 BuildToCapturePreviewPin(pVidCap, &pVidCapPin, &pVidPrevPin, pAudCap, &pAudCapPin, &pAudPrevPin);
9674 // if(pVidCap)
9676 bool fVidPrev = pVidPrevPin && fVPreview;
9677 bool fVidCap = pVidCapPin && fVCapture && fFileOutput && m_wndCaptureBar.m_capdlg.m_fVidOutput;
9679 if(fVPreview == 2 && !fVidCap && pVidCapPin)
9681 pVidPrevPin = pVidCapPin;
9682 pVidCapPin = NULL;
9685 if(fVidPrev)
9687 m_pCAP = NULL;
9688 pGB->Render(pVidPrevPin);
9689 pGB->FindInterface(__uuidof(ISubPicAllocatorPresenter), (void**)&m_pCAP, TRUE);
9692 if(fVidCap)
9694 IBaseFilter* pBF[3] = {pVidBuffer, pVidEnc, pMux};
9695 HRESULT hr = BuildCapture(pVidCapPin, pBF, MEDIATYPE_Video, &m_wndCaptureBar.m_capdlg.m_mtcv);
9698 pAMDF = NULL;
9699 pCGB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pVidCap, IID_IAMDroppedFrames, (void**)&pAMDF);
9702 // if(pAudCap)
9704 bool fAudPrev = pAudPrevPin && fAPreview;
9705 bool fAudCap = pAudCapPin && fACapture && fFileOutput && m_wndCaptureBar.m_capdlg.m_fAudOutput;
9707 if(fAPreview == 2 && !fAudCap && pAudCapPin)
9709 pAudPrevPin = pAudCapPin;
9710 pAudCapPin = NULL;
9713 if(fAudPrev)
9715 pGB->Render(pAudPrevPin);
9718 if(fAudCap)
9720 IBaseFilter* pBF[3] = {pAudBuffer, pAudEnc, pAudMux ? pAudMux : pMux};
9721 HRESULT hr = BuildCapture(pAudCapPin, pBF, MEDIATYPE_Audio, &m_wndCaptureBar.m_capdlg.m_mtca);
9725 if((pVidCap || pAudCap) && fCapture && fFileOutput)
9727 if(pMux != pDst)
9729 hr = pGB->AddFilter(pDst, L"File Writer V/A");
9730 hr = pGB->ConnectFilter(GetFirstPin(pMux, PINDIR_OUTPUT), pDst);
9733 if(CComQIPtr<IConfigAviMux> pCAM = pMux)
9735 int nIn, nOut, nInC, nOutC;
9736 CountPins(pMux, nIn, nOut, nInC, nOutC);
9737 pCAM->SetMasterStream(nInC-1);
9738 // pCAM->SetMasterStream(-1);
9739 pCAM->SetOutputCompatibilityIndex(FALSE);
9742 if(CComQIPtr<IConfigInterleaving> pCI = pMux)
9744 // if(FAILED(pCI->put_Mode(INTERLEAVE_CAPTURE)))
9745 if(FAILED(pCI->put_Mode(INTERLEAVE_NONE_BUFFERED)))
9746 pCI->put_Mode(INTERLEAVE_NONE);
9748 REFERENCE_TIME rtInterleave = 10000i64*AUDIOBUFFERLEN, rtPreroll = 0;//10000i64*500
9749 pCI->put_Interleaving(&rtInterleave, &rtPreroll);
9752 if(pMux != pAudMux && pAudMux != pAudDst)
9754 hr = pGB->AddFilter(pAudDst, L"File Writer A");
9755 hr = pGB->ConnectFilter(GetFirstPin(pAudMux, PINDIR_OUTPUT), pAudDst);
9759 REFERENCE_TIME stop = MAX_TIME;
9760 hr = pCGB->ControlStream(&PIN_CATEGORY_CAPTURE, NULL, NULL, NULL, &stop, 0, 0); // stop in the infinite
9762 CleanGraph();
9764 OpenSetupVideo();
9765 OpenSetupAudio();
9766 OpenSetupStatsBar();
9767 OpenSetupStatusBar();
9769 RestoreMediaState;
9771 return(true);
9774 bool CMainFrame::StartCapture()
9776 if(!pCGB || m_fCapturing) return(false);
9778 if(!m_wndCaptureBar.m_capdlg.m_pMux && !m_wndCaptureBar.m_capdlg.m_pDst) return(false);
9780 HRESULT hr;
9782 ::SetPriorityClass(::GetCurrentProcess(), HIGH_PRIORITY_CLASS);
9784 // rare to see two capture filters to support IAMPushSource at the same time...
9785 // hr = CComQIPtr<IAMGraphStreams>(pGB)->SyncUsingStreamOffset(TRUE); // TODO:
9787 BuildGraphVideoAudio(
9788 m_wndCaptureBar.m_capdlg.m_fVidPreview, true,
9789 m_wndCaptureBar.m_capdlg.m_fAudPreview, true);
9791 hr = pME->CancelDefaultHandling(EC_REPAINT);
9793 SendMessage(WM_COMMAND, ID_PLAY_PLAY);
9795 m_fCapturing = true;
9797 return(true);
9800 bool CMainFrame::StopCapture()
9802 if(!pCGB || !m_fCapturing) return(false);
9804 if(!m_wndCaptureBar.m_capdlg.m_pMux && !m_wndCaptureBar.m_capdlg.m_pDst) return(false);
9806 HRESULT hr;
9808 m_wndStatusBar.SetStatusMessage(ResStr(IDS_CONTROLS_COMPLETING));
9810 m_fCapturing = false;
9812 BuildGraphVideoAudio(
9813 m_wndCaptureBar.m_capdlg.m_fVidPreview, false,
9814 m_wndCaptureBar.m_capdlg.m_fAudPreview, false);
9816 hr = pME->RestoreDefaultHandling(EC_REPAINT);
9818 ::SetPriorityClass(::GetCurrentProcess(), AfxGetAppSettings().priority);
9820 m_rtDurationOverride = -1;
9822 return(true);
9827 void CMainFrame::ShowOptions(int idPage)
9829 AppSettings& s = AfxGetAppSettings();
9831 CPPageSheet options(ResStr(IDS_OPTIONS_CAPTION), pGB, this, idPage);
9833 if(options.DoModal() == IDOK)
9835 if(!m_fFullScreen)
9836 SetAlwaysOnTop(s.iOnTop);
9838 m_wndView.LoadLogo();
9840 s.UpdateData(true);
9844 void CMainFrame::StartWebServer(int nPort)
9846 if(!m_pWebServer)
9847 m_pWebServer.Attach(new CWebServer(this, nPort));
9850 void CMainFrame::StopWebServer()
9852 if(m_pWebServer)
9853 m_pWebServer.Free();
9856 CString CMainFrame::GetStatusMessage()
9858 CString str;
9859 m_wndStatusBar.m_status.GetWindowText(str);
9860 return str;
9863 void CMainFrame::SendStatusMessage(CString msg, int nTimeOut)
9865 KillTimer(TIMER_STATUSERASER);
9867 m_playingmsg.Empty();
9868 if(nTimeOut <= 0) return;
9870 m_playingmsg = msg;
9871 SetTimer(TIMER_STATUSERASER, nTimeOut, NULL);
9874 void CMainFrame::OpenCurPlaylistItem(REFERENCE_TIME rtStart)
9876 if(m_wndPlaylistBar.GetCount() == 0)
9877 return;
9879 CPlaylistItem pli;
9880 if(!m_wndPlaylistBar.GetCur(pli)) m_wndPlaylistBar.SetFirst();
9881 if(!m_wndPlaylistBar.GetCur(pli)) return;
9883 CAutoPtr<OpenMediaData> p(m_wndPlaylistBar.GetCurOMD(rtStart));
9884 if(p) OpenMedia(p);
9887 void CMainFrame::AddCurDevToPlaylist()
9889 if(m_iPlaybackMode == PM_CAPTURE)
9891 m_wndPlaylistBar.Append(
9892 m_VidDispName,
9893 m_AudDispName,
9894 m_wndCaptureBar.m_capdlg.GetVideoInput(),
9895 m_wndCaptureBar.m_capdlg.GetVideoChannel(),
9896 m_wndCaptureBar.m_capdlg.GetAudioInput()
9901 static int s_fOpenedThruThread = false;
9903 void CMainFrame::OpenMedia(CAutoPtr<OpenMediaData> pOMD)
9905 // shortcut
9906 if(OpenDeviceData* p = dynamic_cast<OpenDeviceData*>(pOMD.m_p))
9908 if(m_iMediaLoadState == MLS_LOADED && pAMTuner
9909 && m_VidDispName == p->DisplayName[0] && m_AudDispName == p->DisplayName[1])
9911 m_wndCaptureBar.m_capdlg.SetVideoInput(p->vinput);
9912 m_wndCaptureBar.m_capdlg.SetVideoChannel(p->vchannel);
9913 m_wndCaptureBar.m_capdlg.SetAudioInput(p->ainput);
9914 SendNowPlayingToMSN();
9915 SendNowPlayingTomIRC();
9916 return;
9920 if(m_iMediaLoadState != MLS_CLOSED)
9921 CloseMedia();
9923 m_iMediaLoadState = MLS_LOADING; // HACK: hides the logo
9925 AppSettings& s = AfxGetAppSettings();
9927 bool fUseThread = true;
9929 if(OpenFileData* p = dynamic_cast<OpenFileData*>(pOMD.m_p))
9931 if(p->fns.GetCount() > 0)
9933 engine_t e = s.Formats.GetEngine(p->fns.GetHead());
9934 fUseThread = e == DirectShow /*|| e == RealMedia || e == QuickTime*/;
9937 else if(OpenDeviceData* p = dynamic_cast<OpenDeviceData*>(pOMD.m_p))
9939 fUseThread = false;
9942 if(m_pGraphThread && fUseThread
9943 && AfxGetAppSettings().fEnableWorkerThreadForOpening)
9945 m_pGraphThread->PostThreadMessage(CGraphThread::TM_OPEN, 0, (LPARAM)pOMD.Detach());
9946 s_fOpenedThruThread = true;
9948 else
9950 OpenMediaPrivate(pOMD);
9951 s_fOpenedThruThread = false;
9955 void CMainFrame::CloseMedia()
9957 if(m_iMediaLoadState == MLS_CLOSING)
9959 TRACE(_T("WARNING: CMainFrame::CloseMedia() called twice or more\n"));
9960 return;
9963 int nTimeWaited = 0;
9965 while(m_iMediaLoadState == MLS_LOADING)
9967 m_fOpeningAborted = true;
9969 if(pGB) pGB->Abort(); // TODO: lock on graph objects somehow, this is not thread safe
9971 if(nTimeWaited > 5*1000 && m_pGraphThread)
9973 MessageBeep(MB_ICONEXCLAMATION);
9974 TRACE(_T("CRITICAL ERROR: !!! Must kill opener thread !!!"));
9975 TerminateThread(m_pGraphThread->m_hThread, -1);
9976 m_pGraphThread = (CGraphThread*)AfxBeginThread(RUNTIME_CLASS(CGraphThread));
9977 s_fOpenedThruThread = false;
9978 break;
9981 Sleep(50);
9983 nTimeWaited += 50;
9986 m_fOpeningAborted = false;
9988 m_closingmsg.Empty();
9990 m_iMediaLoadState = MLS_CLOSING;
9992 OnFilePostClosemedia();
9994 if(m_pGraphThread && s_fOpenedThruThread)
9996 CAMEvent e;
9997 m_pGraphThread->PostThreadMessage(CGraphThread::TM_CLOSE, 0, (LPARAM)&e);
9998 e.Wait(); // either opening or closing has to be blocked to prevent reentering them, closing is the better choice
10000 else
10002 CloseMediaPrivate();
10005 UnloadExternalObjects();
10009 // CGraphThread
10012 IMPLEMENT_DYNCREATE(CGraphThread, CWinThread)
10014 BOOL CGraphThread::InitInstance()
10016 AfxSocketInit();
10017 return SUCCEEDED(CoInitialize(0)) ? TRUE : FALSE;
10020 int CGraphThread::ExitInstance()
10022 CoUninitialize();
10023 return __super::ExitInstance();
10026 BEGIN_MESSAGE_MAP(CGraphThread, CWinThread)
10027 ON_THREAD_MESSAGE(TM_EXIT, OnExit)
10028 ON_THREAD_MESSAGE(TM_OPEN, OnOpen)
10029 ON_THREAD_MESSAGE(TM_CLOSE, OnClose)
10030 END_MESSAGE_MAP()
10032 void CGraphThread::OnExit(WPARAM wParam, LPARAM lParam)
10034 PostQuitMessage(0);
10035 if(CAMEvent* e = (CAMEvent*)lParam) e->Set();
10038 void CGraphThread::OnOpen(WPARAM wParam, LPARAM lParam)
10040 if(m_pMainFrame)
10042 CAutoPtr<OpenMediaData> pOMD((OpenMediaData*)lParam);
10043 m_pMainFrame->OpenMediaPrivate(pOMD);
10047 void CGraphThread::OnClose(WPARAM wParam, LPARAM lParam)
10049 if(m_pMainFrame) m_pMainFrame->CloseMediaPrivate();
10050 if(CAMEvent* e = (CAMEvent*)lParam) e->Set();
10053 afx_msg void CMainFrame::OnSubtitleDelay(UINT nID)
10055 if(m_pCAP) {
10056 int newDelay;
10057 int oldDelay = m_pCAP->GetSubtitleDelay();
10059 if(nID == ID_SUB_DELAY_DOWN)
10060 newDelay = oldDelay-AfxGetAppSettings().nSubDelayInterval;
10061 else
10062 newDelay = oldDelay+AfxGetAppSettings().nSubDelayInterval;
10064 SetSubtitleDelay(newDelay);