source: trunk/Utilities/RenderInterlacedVideo/MainPropertySheet.h @ 297

Last change on this file since 297 was 297, checked in by roman, 8 years ago
  • Property svn:keywords set to Id
File size: 63.9 KB
Line 
1////////////////////////////////////////////////////////////
2// Copyright (C) Roman Ryltsov, 2008-2014
3// Created by Roman Ryltsov roman@alax.info
4
5#pragma once
6
7#include "AboutDialog.h"
8#include <dshow.h>
9#include <d3d9.h>
10#include <vmr9.h>
11#include <evr.h>
12#include <evr9.h>
13#include <dxva.h>
14#import "libid:B9EC374B-834B-4DA9-BFB5-C1872CE736FF" raw_interfaces_only // AlaxInfoDirectShowSpy
15#include "rodshow.h"
16
17////////////////////////////////////////////////////////////
18// CVrWindowT
19
20template <typename T>
21class CVrWindowT
22{
23public:
24// CVrWindowT
25        VOID DoHelperModal(IUnknown* pUnknown, LPCTSTR pszCaption = NULL)
26        {
27                T* pT = static_cast<T*>(this);
28                CComPtr<AlaxInfoDirectShowSpy::IFilterGraphHelper> pFilterGraphHelper;
29                const HRESULT nCoCreateInstanceResult = pFilterGraphHelper.CoCreateInstance(__uuidof(AlaxInfoDirectShowSpy::FilterGraphHelper));
30                if(SUCCEEDED(nCoCreateInstanceResult))
31                {
32                        __C(pFilterGraphHelper->put_FilterGraph(pUnknown));
33                        __C(pFilterGraphHelper->DoPropertyFrameModal((LONG) (LONG_PTR) pT->m_hWnd));
34                        return;
35                }
36                COlePropertyFrameDialog Dialog(pUnknown, pszCaption);
37                Dialog.SetObjectPages();
38                Dialog.DoModal(pT->m_hWnd);
39        }
40};
41
42////////////////////////////////////////////////////////////
43// CVmr7Window
44
45class CVmr7Window :
46        public CControlWindowT<CVmr7Window>,
47        public CVrWindowT<CVmr7Window>
48{
49public:
50
51BEGIN_MSG_MAP_EX(CVmr7Window)
52        //CHAIN_MSG_MAP(CControlWindowT<CVmr7Window>)
53        MSG_WM_ERASEBKGND(OnEraseBkgnd)
54        MSG_WM_PAINT(OnPaint)
55        MSG_WM_DISPLAYCHANGE(OnDisplayChange)
56        MSG_WM_SIZE(OnSize)
57        MSG_WM_LBUTTONDBLCLK(OnLButtonDblClk)
58END_MSG_MAP()
59
60public:
61        CComPtr<IBaseFilter> m_pBaseFilter;
62        CComPtr<IVMRWindowlessControl> m_pVmrWindowlessControl;
63
64public:
65// CVmr7Window
66        static CLSID GetRendererClassIdentifier()
67        {
68                return CLSID_VideoMixingRenderer;
69        }
70        static CComPtr<IBaseFilter> CoCreateBaseFilterInstance()
71        {
72                CComPtr<IBaseFilter> pBaseFilter;
73                __C(pBaseFilter.CoCreateInstance(GetRendererClassIdentifier()));
74                return pBaseFilter;
75        }
76        VOID Initialize(IBaseFilter* pBaseFilter)
77        {
78                _A(pBaseFilter);
79                _A(!m_pBaseFilter && !m_pVmrWindowlessControl);
80                m_pBaseFilter = pBaseFilter;
81                CComQIPtr<IVMRFilterConfig> pVmrFilterConfig = pBaseFilter;
82                __D(pVmrFilterConfig, E_NOINTERFACE);
83                __C(pVmrFilterConfig->SetRenderingMode(VMRMode_Windowless));
84                // NOTE: Cause the VMR to load the mixer and compositor
85                //       See http://msdn.microsoft.com/en-us/library/windows/desktop/dd390448%28v=vs.85%29.aspx
86                __C(pVmrFilterConfig->SetNumberOfStreams(1));
87                m_pVmrWindowlessControl = CComQIPtr<IVMRWindowlessControl>(m_pBaseFilter);
88                __D(m_pVmrWindowlessControl, E_NOINTERFACE);
89                __C(m_pVmrWindowlessControl->SetVideoClippingWindow(m_hWnd));
90                UpdateVideoPosition();
91        }
92        VOID Terminate()
93        {
94                m_pBaseFilter = NULL;
95                m_pVmrWindowlessControl = NULL;
96        }
97        CRect GetVideoPosition() const
98        {
99                CRect Position;
100                _W(GetClientRect(Position));
101                return Position;
102        }
103        BOOL UpdateVideoPosition()
104        {
105                _A(m_pVmrWindowlessControl && IsWindow());
106                CRect VideoPosition = GetVideoPosition();
107                _Z4(atlTraceGeneral, 4, _T("m_pVmrWindowlessControl 0x%p, VideoPosition at (%d, %d) size (%d, %d)\n"), m_pVmrWindowlessControl, VideoPosition.left, VideoPosition.top, VideoPosition.Width(), VideoPosition.Height());
108                const HRESULT nSetVideoPositionResult = m_pVmrWindowlessControl->SetVideoPosition(NULL, VideoPosition);
109                __C(nSetVideoPositionResult); //_Z45_DSHRESULT(nSetVideoPositionResult);
110                return SUCCEEDED(nSetVideoPositionResult);
111        }
112
113// Window Message Handlers
114        LRESULT OnEraseBkgnd(CDCHandle Dc)
115        {
116                Dc;
117                if(m_pVmrWindowlessControl)
118                {
119                        return TRUE;
120                } else
121                        SetMsgHandled(FALSE);
122                return 0;
123        }
124        LRESULT OnPaint(CDCHandle)
125        {
126                if(m_pVmrWindowlessControl)
127                {
128                        CPaintDC Dc(m_hWnd);
129                        const HRESULT nRepaintVideoResult = m_pVmrWindowlessControl->RepaintVideo(m_hWnd, Dc);
130                        _Z45_DSHRESULT(nRepaintVideoResult);
131                } else
132                        SetMsgHandled(FALSE);
133                return 0;
134        }
135        LRESULT OnDisplayChange(UINT nDepth, CSize Extent)
136        {
137                if(m_pVmrWindowlessControl)
138                {
139                        const HRESULT nDisplayModeChangedResult = m_pVmrWindowlessControl->DisplayModeChanged();
140                        _Z4_DSHRESULT(nDisplayModeChangedResult);
141                }
142                return 0;
143        }
144        LRESULT OnSize(UINT nType, CSize)
145        {
146                if(nType != SIZE_MINIMIZED)
147                        if(m_pVmrWindowlessControl)
148                                UpdateVideoPosition();
149                return 0;
150        }
151        LRESULT OnLButtonDblClk(UINT, CPoint Position)
152        {
153                DoHelperModal(m_pBaseFilter, _T("VMR-7"));
154                return 0;
155        }
156};
157
158////////////////////////////////////////////////////////////
159// CVmr9Window
160
161class CVmr9Window :
162        public CControlWindowT<CVmr9Window>,
163        public CVrWindowT<CVmr9Window>
164{
165public:
166
167BEGIN_MSG_MAP_EX(CVmr9Window)
168        //CHAIN_MSG_MAP(CControlWindowT<CVmr9Window>)
169        MSG_WM_ERASEBKGND(OnEraseBkgnd)
170        MSG_WM_PAINT(OnPaint)
171        MSG_WM_DISPLAYCHANGE(OnDisplayChange)
172        MSG_WM_SIZE(OnSize)
173        MSG_WM_LBUTTONDBLCLK(OnLButtonDblClk)
174END_MSG_MAP()
175
176public:
177
178        ////////////////////////////////////////////////////////
179        // CMonitorInformation
180
181        class CMonitorInformation
182        {
183        public:
184                CComPtr<IVMRMonitorConfig9> m_pVmrMonitorConfig;
185                CTempBufferT<VMR9MonitorInfo> m_pMonitorInformations;
186                SIZE_T m_nMonitorInformationCount;
187
188        public:
189        // CMonitorInformation
190                CMonitorInformation() :
191                        m_nMonitorInformationCount(0)
192                {
193                }
194                CMonitorInformation(IVMRMonitorConfig9* pVmrMonitorConfig) :
195                        m_nMonitorInformationCount(0)
196                {
197                        Initialize(pVmrMonitorConfig);
198                }
199                CMonitorInformation(IUnknown* pUnknown) :
200                        m_nMonitorInformationCount(0)
201                {
202                        Initialize(pUnknown);
203                }
204                VOID Initialize(IVMRMonitorConfig9* pVmrMonitorConfig)
205                {
206                        _A(pVmrMonitorConfig);
207                        m_pVmrMonitorConfig = pVmrMonitorConfig;
208                        DWORD nMonitorInformationCount = 0;
209                        m_pVmrMonitorConfig->GetAvailableMonitors(NULL, 0, &nMonitorInformationCount);
210                        if(nMonitorInformationCount < 32)
211                                nMonitorInformationCount = 32;
212                        m_pMonitorInformations.Free();
213                        _W(m_pMonitorInformations.Allocate(nMonitorInformationCount));
214                        __C(m_pVmrMonitorConfig->GetAvailableMonitors(m_pMonitorInformations, nMonitorInformationCount, &nMonitorInformationCount));
215                        m_nMonitorInformationCount = nMonitorInformationCount;
216                }
217                VOID Initialize(IUnknown* pUnknown)
218                {
219                        const CComQIPtr<IVMRMonitorConfig9> pVmrMonitorConfig = pUnknown;
220                        __D(pVmrMonitorConfig, E_NOINTERFACE);
221                        Initialize(pVmrMonitorConfig);
222                }
223                VOID TraceMonitor() const
224                {
225                        #if _DEVELOPMENT
226                                _A(m_pVmrMonitorConfig);
227                                UINT nMonitor, nDefaultMonitor;
228                                __C(m_pVmrMonitorConfig->GetMonitor(&nMonitor));
229                                __C(m_pVmrMonitorConfig->GetDefaultMonitor(&nDefaultMonitor));
230                                _Z4(atlTraceGeneral, 4, _T("nMonitor %d, nDefaultMonitor %d\n"), nMonitor, nDefaultMonitor);
231                        #endif // _DEVELOPMENT
232                }
233                BOOL SuggestMonitor(RECT Position, UINT& nSuggestMonitor) const
234                {
235                        BOOL bSuggestMonitorAvailable = FALSE;
236                        LONG nSuggestMonitorScore;
237                        for(DWORD nIndex = 0; nIndex < m_nMonitorInformationCount; nIndex++)
238                        {
239                                const VMR9MonitorInfo& MonitorInformation = m_pMonitorInformations[nIndex];
240                                const CRect& MonitorPosition = reinterpret_cast<const CRect&>(MonitorInformation.rcMonitor);
241                                _Z4(atlTraceGeneral, 4, _T("MonitorInformation.uDevID %d, .hMon 0x%08X, .dwFlags 0x%X, .szDevice \"%ls\", .szDescription \"%ls\"\n"), 
242                                        MonitorInformation.uDevID,
243                                        //MonitorInformation.rcMonitor.left, ...
244                                        MonitorInformation.hMon, MonitorInformation.dwFlags, 
245                                        MonitorInformation.szDevice, MonitorInformation.szDescription,
246                                        //MonitorInformation.liDriverVersion,
247                                        //MonitorInformation.dwVendorId, MonitorInformation.dwDeviceId, MonitorInformation.dwSubSysId, MonitorInformation.dwRevision,
248                                        0);
249                                CRect VisiblePosition;
250                                if(!VisiblePosition.IntersectRect(MonitorPosition, &Position))
251                                        continue;
252                                const LONG nScore = VisiblePosition.Height() * VisiblePosition.Width();
253                                if(bSuggestMonitorAvailable && nSuggestMonitorScore > nScore)
254                                        continue;
255                                nSuggestMonitor = MonitorInformation.uDevID;
256                                bSuggestMonitorAvailable = TRUE;
257                                nSuggestMonitorScore = nScore;
258                        }
259                        return bSuggestMonitorAvailable;
260                }
261        };
262
263public:
264        CComPtr<IBaseFilter> m_pBaseFilter;
265        CComPtr<IVMRWindowlessControl9> m_pVmrWindowlessControl;
266
267public:
268// CVmr9Window
269        static CLSID GetRendererClassIdentifier()
270        {
271                return CLSID_VideoMixingRenderer9;
272        }
273        static CComPtr<IBaseFilter> CoCreateBaseFilterInstance()
274        {
275                CComPtr<IBaseFilter> pBaseFilter;
276                __C(pBaseFilter.CoCreateInstance(GetRendererClassIdentifier()));
277                return pBaseFilter;
278        }
279        VOID Initialize(IBaseFilter* pBaseFilter)
280        {
281                _A(pBaseFilter);
282                _A(!m_pBaseFilter && !m_pVmrWindowlessControl);
283                m_pBaseFilter = pBaseFilter;
284                CComQIPtr<IVMRFilterConfig9> pVmrFilterConfig = pBaseFilter;
285                __D(pVmrFilterConfig, E_NOINTERFACE);
286                __C(pVmrFilterConfig->SetRenderingMode(VMR9Mode_Windowless));
287                m_pVmrWindowlessControl = CComQIPtr<IVMRWindowlessControl9>(m_pBaseFilter);
288                __D(m_pVmrWindowlessControl, E_NOINTERFACE);
289                __C(m_pVmrWindowlessControl->SetVideoClippingWindow(m_hWnd));
290                UpdateVideoPosition();
291        }
292        VOID Terminate()
293        {
294                m_pBaseFilter = NULL;
295                m_pVmrWindowlessControl = NULL;
296        }
297        CRect GetVideoPosition() const
298        {
299                CRect Position;
300                _W(GetClientRect(Position));
301                return Position;
302        }
303        BOOL UpdateVideoPosition()
304        {
305                _A(m_pVmrWindowlessControl && IsWindow());
306                CRect VideoPosition = GetVideoPosition();
307                _Z4(atlTraceGeneral, 4, _T("m_pVmrWindowlessControl 0x%p, VideoPosition at (%d, %d) size (%d, %d)\n"), m_pVmrWindowlessControl, VideoPosition.left, VideoPosition.top, VideoPosition.Width(), VideoPosition.Height());
308                const HRESULT nSetVideoPositionResult = m_pVmrWindowlessControl->SetVideoPosition(NULL, VideoPosition);
309                __C(nSetVideoPositionResult); //_Z45_DSHRESULT(nSetVideoPositionResult);
310                return SUCCEEDED(nSetVideoPositionResult);
311        }
312
313// Window Message Handlers
314        LRESULT OnEraseBkgnd(CDCHandle Dc)
315        {
316                Dc;
317                if(m_pVmrWindowlessControl)
318                {
319                        return TRUE;
320                } else
321                        SetMsgHandled(FALSE);
322                return 0;
323        }
324        LRESULT OnPaint(CDCHandle)
325        {
326                if(m_pVmrWindowlessControl)
327                {
328                        CPaintDC Dc(m_hWnd);
329                        const HRESULT nRepaintVideoResult = m_pVmrWindowlessControl->RepaintVideo(m_hWnd, Dc);
330                        _Z45_DSHRESULT(nRepaintVideoResult);
331                } else
332                        SetMsgHandled(FALSE);
333                return 0;
334        }
335        LRESULT OnDisplayChange(UINT nDepth, CSize Extent)
336        {
337                if(m_pVmrWindowlessControl)
338                {
339                        const HRESULT nDisplayModeChangedResult = m_pVmrWindowlessControl->DisplayModeChanged();
340                        _Z45_DSHRESULT(nDisplayModeChangedResult);
341                }
342                return 0;
343        }
344        LRESULT OnSize(UINT nType, CSize)
345        {
346                if(nType != SIZE_MINIMIZED)
347                        if(m_pVmrWindowlessControl)
348                                UpdateVideoPosition();
349                return 0;
350        }
351        LRESULT OnLButtonDblClk(UINT, CPoint Position)
352        {
353                DoHelperModal(m_pBaseFilter, _T("VMR-9"));
354                return 0;
355        }
356};
357
358////////////////////////////////////////////////////////////
359// CEvrWindow
360
361class CEvrWindow :
362        public CControlWindowT<CEvrWindow>,
363        public CVrWindowT<CEvrWindow>
364{
365public:
366
367BEGIN_MSG_MAP_EX(CEvrWindow)
368        //CHAIN_MSG_MAP(CControlWindowT<CEvrWindow>)
369        MSG_WM_ERASEBKGND(OnEraseBkgnd)
370        MSG_WM_PAINT(OnPaint)
371        MSG_WM_SIZE(OnSize)
372        MSG_WM_LBUTTONDBLCLK(OnLButtonDblClk)
373END_MSG_MAP()
374
375public:
376        CComPtr<IBaseFilter> m_pBaseFilter;
377        CComPtr<IMFVideoDisplayControl> m_pMfVideoDisplayControl;
378
379public:
380// CEvrWindow
381        static CLSID GetRendererClassIdentifier()
382        {
383                return CLSID_EnhancedVideoRenderer;
384        }
385        static CComPtr<IBaseFilter> CoCreateBaseFilterInstance()
386        {
387                CComPtr<IBaseFilter> pBaseFilter;
388                __C(pBaseFilter.CoCreateInstance(GetRendererClassIdentifier()));
389                return pBaseFilter;
390        }
391        VOID Initialize(IBaseFilter* pBaseFilter)
392        {
393                _A(pBaseFilter);
394                _A(!m_pBaseFilter && !m_pMfVideoDisplayControl);
395                m_pBaseFilter = pBaseFilter;
396                CComQIPtr<IMFGetService> pMfGetInterface = pBaseFilter;
397                CComPtr<IMFVideoDisplayControl> pMfVideoDisplayControl;
398                __C(pMfGetInterface->GetService(MR_VIDEO_RENDER_SERVICE, __uuidof(IMFVideoDisplayControl), (VOID**) &pMfVideoDisplayControl));
399                _A(pMfVideoDisplayControl);
400                m_pMfVideoDisplayControl = pMfVideoDisplayControl;
401                __C(pMfVideoDisplayControl->SetVideoWindow(m_hWnd));
402                UpdateVideoPosition();
403                //__C(pMfVideoDisplayControl->SetAspectRatioMode(MFVideoARMode_None)); // As opposed to default MFVideoARMode_Picture - disable letterboxing
404        }
405        VOID Terminate()
406        {
407                m_pBaseFilter = NULL;
408                m_pMfVideoDisplayControl = NULL;
409        }
410        CRect GetVideoPosition() const
411        {
412                CRect Position;
413                _W(GetClientRect(Position));
414                return Position;
415        }
416        BOOL UpdateVideoPosition()
417        {
418                _A(m_pMfVideoDisplayControl && IsWindow());
419                CRect VideoPosition = GetVideoPosition();
420                _Z4(atlTraceGeneral, 4, _T("m_pMfVideoDisplayControl 0x%p, VideoPosition at (%d, %d) size (%d, %d)\n"), m_pMfVideoDisplayControl, VideoPosition.left, VideoPosition.top, VideoPosition.Width(), VideoPosition.Height());
421                const HRESULT nSetVideoPositionResult = m_pMfVideoDisplayControl->SetVideoPosition(NULL, VideoPosition);
422                __C(nSetVideoPositionResult); //_Z45_DSHRESULT(nSetVideoPositionResult);
423                return SUCCEEDED(nSetVideoPositionResult);
424        }
425
426// Window Message Handlers
427        LRESULT OnEraseBkgnd(CDCHandle Dc)
428        {
429                Dc;
430                if(m_pMfVideoDisplayControl)
431                {
432                        return TRUE;
433                } else
434                        SetMsgHandled(FALSE);
435                return 0;
436        }
437        LRESULT OnPaint(CDCHandle)
438        {
439                if(m_pMfVideoDisplayControl)
440                {
441                        CPaintDC Dc(m_hWnd);
442                        const HRESULT nRepaintVideoResult = m_pMfVideoDisplayControl->RepaintVideo();
443                        _Z4(atlTraceUI, SUCCEEDED(nRepaintVideoResult) ? 6 : 4, _T("nRepaintVideoResult 0x%08x\n"), nRepaintVideoResult);
444                } else
445                        SetMsgHandled(FALSE);
446                return 0;
447        }
448        LRESULT OnSize(UINT nType, CSize)
449        {
450                if(nType != SIZE_MINIMIZED)
451                        if(m_pMfVideoDisplayControl)
452                                UpdateVideoPosition();
453                return 0;
454        }
455        LRESULT OnLButtonDblClk(UINT, CPoint Position)
456        {
457                DoHelperModal(m_pBaseFilter, _T("EVR"));
458                return 0;
459        }
460};
461
462////////////////////////////////////////////////////////////
463// CMainPropertySheet
464
465class CMainPropertySheet : 
466        public CSizablePropertySheetT<CMainPropertySheet>
467{
468public:
469
470BEGIN_MSG_MAP_EX(CMainPropertySheet)
471        CHAIN_MSG_MAP(CSizablePropertySheet)
472        MESSAGE_HANDLER_EX(WM_SETLARGERINITIALPOSITION, OnSetLargerInitialPosition)
473END_MSG_MAP()
474
475public:
476
477        ////////////////////////////////////////////////////////
478        // Window Message Identifiers
479
480        enum
481        {
482                MW_FIRST = WM_APP + 100,
483                WM_SETLARGERINITIALPOSITION,
484        };
485
486        ////////////////////////////////////////////////////////
487        // CSourceFilter
488
489        class ATL_NO_VTABLE CSourceFilter :
490                public CComObjectRootEx<CComMultiThreadModelNoCS>,
491                public CComCoClass<CSourceFilter>,
492                public CPushSourceFilterT<CSourceFilter>,
493                public CBasePersistT<CSourceFilter>,
494                public CAmFilterMiscFlagsT<CSourceFilter, AM_FILTER_MISC_FLAGS_IS_SOURCE>
495        {
496        public:
497
498        DECLARE_NO_REGISTRY()
499
500        DECLARE_PROTECT_FINAL_CONSTRUCT()
501
502        //DECLARE_QI_TRACE(CSourceFilter)
503
504        BEGIN_COM_MAP(CSourceFilter)
505                COM_INTERFACE_ENTRY(IBaseFilter)
506                COM_INTERFACE_ENTRY(IMediaFilter)
507                COM_INTERFACE_ENTRY_IID(__uuidof(IPersist), IBaseFilter)
508                COM_INTERFACE_ENTRY(IAMFilterMiscFlags)
509        END_COM_MAP()
510
511        public:
512
513                ////////////////////////////////////////////////////////
514                // CThreadContext
515
516                class CThreadContext :
517                        public CPushSourceFilter::CThreadContext
518                {
519                public:
520                        SIZE_T m_nMediaSampleIndex;
521
522                public:
523                // CThreadContext
524                        CThreadContext(CEvent& TerminationEvent) :
525                                CPushSourceFilter::CThreadContext(TerminationEvent),
526                                m_nMediaSampleIndex(0)
527                        {
528                        }
529                };
530
531                ////////////////////////////////////////////////////////
532                // COutputPin
533
534                class ATL_NO_VTABLE COutputPin :
535                        public CComObjectRootEx<CComMultiThreadModelNoCS>,
536                        public CPushSourceFilterT<CSourceFilter>::COutputPinT<COutputPin, CSourceFilter, CThreadContext>,
537                        public CAmPushSourceT<COutputPin, 0>
538                {
539                public:
540
541                //DECLARE_QI_TRACE(CSourceFilter::COutputPin)
542
543                BEGIN_COM_MAP(COutputPin)
544                        COM_INTERFACE_ENTRY(IPin)
545                        COM_INTERFACE_ENTRY(IAMPushSource)
546                        COM_INTERFACE_ENTRY(IAMLatency)
547                END_COM_MAP()
548
549                private:
550
551                        VOID Paint(BYTE* pnData, SSIZE_T nNextRowOffset, BYTE nColor)
552                        {
553                                // 400 px high from 40, 60 px wide from current, line step 2
554                                for(LONG nY = (480 - 2 * 40) / 2; nY > 0; nY--)
555                                {
556                                        for(LONG nX = 0; nX < 60; nX++)
557                                                pnData[nX * 2] = nColor;
558                                        pnData += 2 * nNextRowOffset;
559                                }
560                        }
561
562                public:
563                // COutputPin
564                        COutputPin()
565                        {
566                                _Z4(atlTraceRefcount, 4, _T("this 0x%p\n"), this);
567                        }
568                        ~COutputPin()
569                        {
570                                _Z4(atlTraceRefcount, 4, _T("this 0x%p\n"), this);
571                        }
572                        VOID EnumerateMediaTypes(CAtlList<CMediaType>& MediaTypeList)
573                        {
574                                //CRoCriticalSectionLock DataLock(GetDataCriticalSection());
575                                _W(MediaTypeList.AddTail(GetFilter()->m_pRequestedMediaType));
576                        }
577                        BOOL CheckMediaType(const CMediaType& pMediaType) const
578                        {
579                                _A(pMediaType);
580                                if(pMediaType->majortype != MEDIATYPE_Video)
581                                        return FALSE;
582                                //CRoCriticalSectionLock DataLock(GetDataCriticalSection());
583                                _A(GetFilter()->m_pRequestedMediaType);
584                                //if(GetFilter()->m_pRequestedMediaType.Compare(pMediaType))
585                                //      return TRUE;
586                                return CVideoInfoHeader::Compare(&GetFilter()->m_pRequestedMediaType.GetCompatibleVideoInfoHeader(), &pMediaType.GetCompatibleVideoInfoHeader(), FALSE);
587                        }
588                        BOOL DecideMemAllocatorProperties(IMemAllocator* pMemAllocator, ALLOCATOR_PROPERTIES Properties)
589                        {
590                                static const SIZE_T g_nMiminalBufferCount = 8;
591                                Properties.cBuffers = max(Properties.cBuffers, (LONG) g_nMiminalBufferCount);
592                                CRoCriticalSectionLock DataLock(GetDataCriticalSection());
593                                const CMediaType& pMediaType = GetMediaTypeReference();
594                                const CVideoInfoHeader VideoInfoHeader = pMediaType.GetCompatibleVideoInfoHeader();
595                                const CSize Extent = VideoInfoHeader.GetExtent();
596                                SIZE_T nBufferSize;
597                                if(Extent.cx >= 1080)
598                                {
599                                        // NOTE: At higher resolutions we are good to go with much smaller buffers
600                                        static const UINT g_nPixelBitCount = 7;
601                                        nBufferSize = Extent.cy * Extent.cx * g_nPixelBitCount / 8;
602                                } else
603                                {
604                                        static const UINT g_nPixelBitCount = 14;
605                                        nBufferSize = Extent.cy * Extent.cx * g_nPixelBitCount / 8;
606                                }
607                                return SetMemAllocatorBufferSize(pMemAllocator, Properties, nBufferSize);
608                        }
609                        BOOL ComposeMediaSample(CThreadContext& ThreadContext, IMediaSample* pMediaSample)
610                        {
611                                CMediaSampleProperties OutputProperties(pMediaSample);
612                                HandleMediaTypeChange(OutputProperties);
613                                const CMediaType pMediaType = GetMediaType();
614                                const CVideoInfoHeader2* pVideoInfoHeader2 = pMediaType.GetVideoInfoHeader2();
615                                OutputProperties.dwTypeSpecificFlags = (!(ThreadContext.m_nMediaSampleIndex & 1) ? AM_VIDEO_FLAG_FIELD2 : AM_VIDEO_FLAG_FIELD1);
616                                OutputProperties.dwSampleFlags = AM_SAMPLE_SPLICEPOINT | (ThreadContext.m_nMediaSampleIndex ? 0 : AM_SAMPLE_DATADISCONTINUITY) | AM_SAMPLE_TIMEVALID | AM_SAMPLE_STOPVALID;
617                                OutputProperties.lActual = GetMediaType().GetCompatibleVideoInfoHeader().GetDataSize();
618                                OutputProperties.tStart = ThreadContext.m_nMediaSampleIndex * pVideoInfoHeader2->AvgTimePerFrame / 2;
619                                OutputProperties.tStop = OutputProperties.tStart + 1;
620                                OutputProperties.dwStreamId = 0;
621                                #pragma region Data
622                                FillMemory(OutputProperties.pbBuffer, OutputProperties.lActual, 0x80);
623                                const CSize Extent = pVideoInfoHeader2->GetExtent();
624                                SSIZE_T nFirstRowOffset, nNextRowOffset;
625                                pVideoInfoHeader2->GetData(nFirstRowOffset, nNextRowOffset);
626                                BYTE* pnData = OutputProperties.pbBuffer;
627                                static const REFERENCE_TIME g_nPeriod = 3 * 1000 * 10000i64; // 3 seconds for the move back and forth
628                                REFERENCE_TIME nField2Time = (ThreadContext.m_nMediaSampleIndex & ~1) * pVideoInfoHeader2->AvgTimePerFrame / 2;
629                                REFERENCE_TIME nField1Time = ((ThreadContext.m_nMediaSampleIndex - 1) | 1) * pVideoInfoHeader2->AvgTimePerFrame / 2;
630                                _Z5(atlTraceGeneral, 5, _T("m_nMediaSampleIndex %d, OutputProperties.tStart %s, nField2Time %s, nField1Time %s\n"), 
631                                        ThreadContext.m_nMediaSampleIndex,
632                                        _FilterGraphHelper::FormatReferenceTime(OutputProperties.tStart),
633                                        _FilterGraphHelper::FormatReferenceTime(nField2Time), 
634                                        _FilterGraphHelper::FormatReferenceTime(nField1Time), 
635                                        0);
636                                REFERENCE_TIME nPositionA = nField2Time % g_nPeriod;
637                                LONG nPositionB = (LONG) (abs((g_nPeriod / 2) - nPositionA) * (600 - 60) / (g_nPeriod / 2));
638                                Paint(pnData + nFirstRowOffset + (40 + 1) * nNextRowOffset + (60 + nPositionB) * 2, nNextRowOffset, 0xFF);
639                                REFERENCE_TIME nPositionC = nField1Time % g_nPeriod;
640                                LONG nPositionD = (LONG) (abs((g_nPeriod / 2) - nPositionC) * (600 - 60) / (g_nPeriod / 2));
641                                Paint(pnData + nFirstRowOffset + (40 + 0) * nNextRowOffset + (60 + nPositionD) * 2, nNextRowOffset, GetFilter()->GetColorize() ? 0x00 : 0xFF);
642                                if(GetFilter()->GetWeave())
643                                        OutputProperties.dwTypeSpecificFlags |= AM_VIDEO_FLAG_WEAVE;
644                                #pragma endregion
645                                OutputProperties.Set();
646                                ThreadContext.m_nMediaSampleIndex++;
647                                return TRUE;
648                        }
649                };
650
651        private:
652                CObjectPtr<COutputPin> m_pOutputPin;
653                CMediaType m_pRequestedMediaType;
654                BOOL m_bWeave;
655                BOOL m_bColorize;
656
657        public:
658        // CSourceFilter
659                CSourceFilter() :
660                        CBasePersistT<CSourceFilter>(GetDataCriticalSection()),
661                        m_bWeave(FALSE),
662                        m_bColorize(FALSE)
663                {
664                        _Z4(atlTraceRefcount, 4, _T("this 0x%p\n"), this);
665                }
666                ~CSourceFilter()
667                {
668                        _Z4(atlTraceRefcount, 4, _T("this 0x%p\n"), this);
669                }
670                HRESULT FinalConstruct()
671                {
672                        _ATLTRY
673                        {
674                                m_pOutputPin.Construct()->Initialize(this, L"Output");
675                                AddPin(m_pOutputPin);
676                        }
677                        _ATLCATCH(Exception)
678                        {
679                                _C(Exception);
680                        }
681                        return S_OK;
682                }
683                VOID FinalRelease()
684                {
685                        m_pOutputPin = NULL;
686                }
687                VOID DeliverBeginFlush(IPin*)
688                {
689                        m_pOutputPin->DeliverBeginFlush();
690                }
691                VOID DeliverEndFlush(IPin*)
692                {
693                        m_pOutputPin->DeliverEndFlush();
694                }
695                VOID DeliverNewSegment(IPin*, REFERENCE_TIME nStartTime, REFERENCE_TIME nStopTime, DOUBLE fRate)
696                {
697                        m_pOutputPin->DeliverNewSegment(nStartTime, nStopTime, fRate);
698                }
699                static BOOL CanCue()
700                {
701                        return FALSE;
702                }
703                VOID CueFilter()
704                {
705                        m_pOutputPin->CuePin();
706                }
707                VOID RunFilter(REFERENCE_TIME nStartTime)
708                {
709                        m_pOutputPin->RunPin(nStartTime);
710                }
711                VOID PauseFilter()
712                {
713                        m_pOutputPin->PausePin();
714                }
715                VOID StopFilter()
716                {
717                        m_pOutputPin->StopPin();
718                }
719                const CObjectPtr<COutputPin>& GetOutputPin() const
720                {
721                        return m_pOutputPin;
722                }
723                VOID Initialize()
724                {
725                        _A(!m_pRequestedMediaType);
726                        CMediaType pMediaType;
727                        //pMediaType.AllocateVideoInfo(720, 480, 16, MAKEFOURCC('Y', 'U', 'Y', '2'), 1000 * 10000i64 / 30);
728                        pMediaType.Allocate(MEDIATYPE_Video, MEDIASUBTYPE_YUY2, FORMAT_VideoInfo2, sizeof (VIDEOINFOHEADER2));
729                        CVideoInfoHeader2* pVideoInfoHeader2 = pMediaType.GetVideoInfoHeader2();
730                        CBitmapInfoHeader* pBitmapInfoHeader = &pVideoInfoHeader2->GetBitmapInfoHeader();
731                        pBitmapInfoHeader->biSize = sizeof (BITMAPINFOHEADER);
732                        pBitmapInfoHeader->biWidth = 720;
733                        pBitmapInfoHeader->biHeight = 480;
734                        pBitmapInfoHeader->biPlanes = 1;
735                        pBitmapInfoHeader->biBitCount = 16;
736                        pBitmapInfoHeader->biCompression = MEDIASUBTYPE_YUY2.Data1;
737                        pBitmapInfoHeader->biSizeImage = pBitmapInfoHeader->GetDataSize();
738                        pVideoInfoHeader2->GetSourcePosition().SetRect(0, 0, pBitmapInfoHeader->biWidth, pBitmapInfoHeader->biHeight);
739                        pVideoInfoHeader2->GetTargetPosition().SetRect(0, 0, pBitmapInfoHeader->biWidth, pBitmapInfoHeader->biHeight);
740                        pVideoInfoHeader2->AvgTimePerFrame = 1001 * 10000i64 / 30;
741//                      pVideoInfoHeader2->AvgTimePerFrame *= 10; // Uncomment to slow down 10 times
742                        pVideoInfoHeader2->dwBitRate = (DWORD) (8.0 * pBitmapInfoHeader->biSizeImage * 10000000.0 / pVideoInfoHeader2->AvgTimePerFrame + 0.5 - 1E-6);
743                        pVideoInfoHeader2->dwInterlaceFlags = AMINTERLACE_IsInterlaced | AMINTERLACE_FieldPatBothRegular | AMINTERLACE_DisplayModeBobOrWeave;
744//                      pVideoInfoHeader2->dwInterlaceFlags = 0; // Uncomment to remove interlacing
745                        pVideoInfoHeader2->dwPictAspectRatioX = 720;
746                        pVideoInfoHeader2->dwPictAspectRatioY = 480;
747                        pMediaType->bFixedSizeSamples = TRUE;
748                        pMediaType->lSampleSize = pBitmapInfoHeader->biSizeImage;
749                        m_pRequestedMediaType = pMediaType;
750                }
751                const CMediaType& GetRequestedMediaType() const
752                {
753                        return m_pRequestedMediaType;
754                }
755                BOOL GetWeave() const
756                {
757                        CRoCriticalSectionLock DataLock(GetDataCriticalSection());
758                        return m_bWeave;
759                }
760                VOID SetWeave(BOOL bWeave)
761                {
762                        CRoCriticalSectionLock DataLock(GetDataCriticalSection());
763                        m_bWeave = bWeave;
764                }
765                BOOL GetColorize() const
766                {
767                        CRoCriticalSectionLock DataLock(GetDataCriticalSection());
768                        return m_bColorize;
769                }
770                VOID SetColorize(BOOL bColorize)
771                {
772                        CRoCriticalSectionLock DataLock(GetDataCriticalSection());
773                        m_bColorize = bColorize;
774                }
775        };
776
777        ////////////////////////////////////////////////////////////
778        // CAmGraphBuilderCallback
779
780        class ATL_NO_VTABLE CAmGraphBuilderCallback :
781                public CComObjectRootEx<CComMultiThreadModelNoCS>,
782                public IAMGraphBuilderCallback
783        {
784        public:
785
786        BEGIN_COM_MAP(CAmGraphBuilderCallback)
787                COM_INTERFACE_ENTRY(IAMGraphBuilderCallback)
788        END_COM_MAP()
789
790        public:
791        // CAmGraphBuilderCallback
792                CAmGraphBuilderCallback()
793                {
794                        _Z4(atlTraceRefcount, 4, _T("this 0x%p\n"), this);
795                }
796                ~CAmGraphBuilderCallback()
797                {
798                        _Z4(atlTraceRefcount, 4, _T("this 0x%p\n"), this);
799                }
800                VOID SetGraphBuilder(IUnknown* pGraphBuilderUnknown)
801                {
802                        const CComQIPtr<IObjectWithSite> pObjectWithSite = pGraphBuilderUnknown;
803                        __D(pObjectWithSite, E_NOINTERFACE);
804                        __C(pObjectWithSite->SetSite(this));
805                }
806
807        // IAMGraphBuilderCallback
808                STDMETHOD(SelectedFilter)(IMoniker* pMoniker)
809                {
810                        _Z5(atlTraceCOM, 5, _T("...\n"));
811                        _ATLTRY
812                        {
813                                _A(pMoniker);
814                                CComPtr<IBindCtx> pBindCtx;
815                                __C(CreateBindCtx(0, &pBindCtx));
816                                if(_FilterGraphHelper::IsFilterNonGrata(pMoniker))
817                                        return E_FAIL;
818                                const CStringW sMonikerDisplayName = _FilterGraphHelper::GetMonikerDisplayName(pMoniker, pBindCtx);
819                                CComPtr<IPropertyBag> pPropertyBag;
820                                __C(pMoniker->BindToStorage(pBindCtx, NULL, __uuidof(IPropertyBag), (VOID**) &pPropertyBag));
821                                const CStringW sFriendlyName = _FilterGraphHelper::ReadPropertyBagString(pPropertyBag, OLESTR("FriendlyName"));
822                                const CStringW sClassIdentifierString = _FilterGraphHelper::ReadPropertyBagString(pPropertyBag, OLESTR("CLSID"));
823                                const CStringW sPath = _RegKeyHelper::QueryStringValue(HKEY_CLASSES_ROOT, AtlFormatString(_T("CLSID\\%ls\\InprocServer32"), sClassIdentifierString));
824                                _Z4(atlTraceGeneral, 4, _T("sMonikerDisplayName \"%ls\", sFriendlyName \"%ls\", sClassIdentifierString %ls, sPath \"%ls\"\n"), sMonikerDisplayName, sFriendlyName, sClassIdentifierString, sPath);
825                        }
826                        _ATLCATCH(Exception)
827                        {
828                                _C(Exception);
829                        }
830                        return S_OK;
831                }
832                STDMETHOD(CreatedFilter)(IBaseFilter* pBaseFilter)
833                {
834                        _Z5(atlTraceCOM, 5, _T("...\n"));
835                        _ATLTRY
836                        {
837                                _A(pBaseFilter);
838                                _Z4(atlTraceGeneral, 4, _T("pBaseFilter %ls \"%ls\"\n"), _FilterGraphHelper::GetFilterClassIdentifierString(pBaseFilter), _FilterGraphHelper::GetFilterName(pBaseFilter));
839                        }
840                        _ATLCATCH(Exception)
841                        {
842                                _C(Exception);
843                        }
844                        return S_OK;
845                }
846        };
847
848        ////////////////////////////////////////////////////
849        // CVrPropertyPageT
850
851        template <typename T>
852        class CVrPropertyPageT
853        {
854        public:
855        // CVrPropertyPageT
856                VOID HandleMediaEvent(LONG nEventCode, LONG_PTR nParameter1, LONG_PTR nParameter2)
857                {
858                        T* pT = static_cast<T*>(this);
859                        switch(nEventCode)
860                        {
861                        #pragma region EC_COMPLETE
862                        case EC_COMPLETE:
863                                _Z2(atlTraceGeneral, 2, _T("Filter Graph EC_COMPLETE (0x%X) Event, nParameter1 0x%08X, nParameter2 0x%08X\n"), nEventCode, nParameter1, nParameter2);
864                                break;
865                        #pragma endregion
866                        #pragma region EC_USERABORT
867                        case EC_USERABORT:
868                                _Z2(atlTraceGeneral, 2, _T("Filter Graph EC_USERABORT (0x%X) Event, nParameter1 0x%08X, nParameter2 0x%08X\n"), nEventCode, nParameter1, nParameter2);
869                                break;
870                        #pragma endregion
871                        #pragma region EC_ERRORABORT
872                        case EC_ERRORABORT:
873                                _Z2(atlTraceGeneral, 2, _T("Filter Graph EC_ERRORABORT (0x%X) Event, nParameter1 0x%08X, nParameter2 0x%08X\n"), nEventCode, nParameter1, nParameter2);
874                                _A(FAILED(nParameter1));
875                                AtlMessageBoxEx(pT->m_hWnd, (LPCTSTR) AtlFormatString(_T("EC_ERRORABORT Event: %s."), Ds::FormatResult((HRESULT) nParameter1).TrimRight(_T("\t\n\r ."))), IDS_ERROR, MB_ICONERROR | MB_OK);
876                                break;
877                        #pragma endregion
878                        #pragma region EC_PAUSED
879                        case EC_PAUSED:
880                                _Z2(atlTraceGeneral, 2, _T("Filter Graph EC_PAUSED (0x%X) Event, nParameter1 0x%08X, nParameter2 0x%08X\n"), nEventCode, nParameter1, nParameter2);
881                                break;
882                        #pragma endregion
883                        #pragma region EC_VMR_RENDERDEVICE_SET
884                        case EC_VMR_RENDERDEVICE_SET:
885                                {
886                                        CString sParameter1;
887                                        switch(nParameter1)
888                                        {
889                                        case VMR_RENDER_DEVICE_OVERLAY:
890                                                sParameter1 = AtlFormatString(_T("VMR_RENDER_DEVICE_OVERLAY (0x%02X)"), nParameter1);
891                                                break;
892                                        case VMR_RENDER_DEVICE_VIDMEM:
893                                                sParameter1 = AtlFormatString(_T("VMR_RENDER_DEVICE_VIDMEM (0x%02X)"), nParameter1);
894                                                break;
895                                        case VMR_RENDER_DEVICE_SYSMEM:
896                                                sParameter1 = AtlFormatString(_T("VMR_RENDER_DEVICE_SYSMEM (0x%02X)"), nParameter1);
897                                                break;
898                                        default:
899                                                sParameter1 = AtlFormatString(_T("0x%02X"), nParameter1);
900
901                                        }
902                                        _Z2(atlTraceGeneral, 2, _T("Filter Graph EC_VMR_RENDERDEVICE_SET (0x%X) Event, nParameter1 %s, nParameter2 0x%08X\n"), nEventCode, sParameter1, nParameter2);
903                                }
904                                break;
905                        #pragma endregion
906                        default:
907                                #pragma region EC_xxx (Development)
908                                #if _DEVELOPMENT
909                                        #define A(x) { x, #x },
910                                        static const struct
911                                        {
912                                                LONG nEventCode;
913                                                LPCSTR pszEventName;
914                                        } g_pMap[] = 
915                                        {
916                                                A(EC_COMPLETE)
917                                                A(EC_USERABORT)
918                                                A(EC_ERRORABORT)
919                                                A(EC_TIME)
920                                                A(EC_REPAINT)
921                                                A(EC_STREAM_ERROR_STOPPED)
922                                                A(EC_STREAM_ERROR_STILLPLAYING)
923                                                A(EC_ERROR_STILLPLAYING)
924                                                A(EC_PALETTE_CHANGED)
925                                                A(EC_VIDEO_SIZE_CHANGED)
926                                                A(EC_QUALITY_CHANGE)
927                                                A(EC_SHUTTING_DOWN)
928                                                A(EC_CLOCK_CHANGED)
929                                                A(EC_PAUSED)
930                                                A(EC_OPENING_FILE)
931                                                A(EC_BUFFERING_DATA)
932                                                A(EC_FULLSCREEN_LOST)
933                                                A(EC_ACTIVATE)
934                                                A(EC_NEED_RESTART)
935                                                A(EC_WINDOW_DESTROYED)
936                                                A(EC_DISPLAY_CHANGED)
937                                                A(EC_STARVATION)
938                                                A(EC_OLE_EVENT)
939                                                A(EC_NOTIFY_WINDOW)
940                                                A(EC_STREAM_CONTROL_STOPPED)
941                                                A(EC_STREAM_CONTROL_STARTED)
942                                                A(EC_END_OF_SEGMENT)
943                                                A(EC_SEGMENT_STARTED)
944                                                A(EC_LENGTH_CHANGED)
945                                                A(EC_DEVICE_LOST)
946                                                A(EC_SAMPLE_NEEDED)
947                                                A(EC_PROCESSING_LATENCY)
948                                                A(EC_SAMPLE_LATENCY)
949                                                A(EC_SCRUB_TIME)
950                                                A(EC_STEP_COMPLETE)
951                                                A(EC_WMT_INDEX_EVENT)
952                                                A(EC_WMT_EVENT)
953                                        };
954                                        #undef A
955                                        BOOL bFound = FALSE;
956                                        for(SIZE_T nIndex = 0; nIndex < DIM(g_pMap); nIndex++)
957                                                if(g_pMap[nIndex].nEventCode == nEventCode)
958                                                {
959                                                        _Z2(atlTraceGeneral, 2, _T("Filter Graph %hs Event, nEventCode 0x%X, nParameter1 0x%08X, nParameter2 0x%08X\n"), g_pMap[nIndex].pszEventName, nEventCode, nParameter1, nParameter2);
960                                                        bFound = TRUE;
961                                                        break;
962                                                }
963                                        if(!bFound)
964                                #endif // _DEVELOPMENT
965                                #pragma endregion
966                                _Z2(atlTraceGeneral, 2, _T("Filter Graph Event, nEventCode 0x%X, nParameter1 0x%08X, nParameter2 0x%08X\n"), nEventCode, nParameter1, nParameter2);
967                        }
968                }
969        };
970
971        ////////////////////////////////////////////////////
972        // CVmr7PropertyPage
973
974        class CVmr7PropertyPage :
975                public CPropertyPageT<CVmr7PropertyPage>,
976                public CDialogResize<CVmr7PropertyPage>,
977                public CVrPropertyPageT<CVmr7PropertyPage>
978        {
979        public:
980                enum { IDD = IDD_MAIN_VMR7 };
981
982        BEGIN_MSG_MAP_EX(CVmr7PropertyPage)
983                CHAIN_MSG_MAP(CPropertyPageT<CVmr7PropertyPage>)
984                CHAIN_MSG_MAP(CDialogResize<CVmr7PropertyPage>)
985                MSG_WM_INITDIALOG(OnInitDialog)
986                MSG_WM_DESTROY(OnDestroy)
987                COMMAND_ID_HANDLER_EX(IDC_MAIN_VMR7_RUN, OnRunButtonClicked)
988                COMMAND_ID_HANDLER_EX(IDC_MAIN_VMR7_PAUSE, OnPauseButtonClicked)
989                COMMAND_ID_HANDLER_EX(IDC_MAIN_VMR7_STOP, OnStopButtonClicked)
990                COMMAND_ID_HANDLER_EX(IDC_MAIN_VMR7_WEAVE, OnWeaveButtonClicked)
991                COMMAND_ID_HANDLER_EX(IDC_MAIN_VMR7_COLORIZE, OnColorizeButtonClicked)
992                MESSAGE_HANDLER_EX(WM_FILTERGRAPHEVENT, OnFilterGraphEvent)
993                REFLECT_NOTIFICATIONS()
994        END_MSG_MAP()
995
996        BEGIN_DLGRESIZE_MAP(CVmr7PropertyPage)
997                DLGRESIZE_CONTROL(IDC_MAIN_VMR7_VIDEO, DLSZ_SIZE_X | DLSZ_SIZE_Y)
998                DLGRESIZE_CONTROL(IDC_MAIN_VMR7_RUN, DLSZ_MOVE_X)
999                DLGRESIZE_CONTROL(IDC_MAIN_VMR7_PAUSE, DLSZ_MOVE_X)
1000                DLGRESIZE_CONTROL(IDC_MAIN_VMR7_STOP, DLSZ_MOVE_X)
1001                DLGRESIZE_CONTROL(IDC_MAIN_VMR7_WEAVE, DLSZ_MOVE_Y)
1002                DLGRESIZE_CONTROL(IDC_MAIN_VMR7_COLORIZE, DLSZ_MOVE_Y)
1003        END_DLGRESIZE_MAP()
1004
1005        public:
1006
1007                ////////////////////////////////////////////////////////
1008                // Window Message Identifiers
1009
1010                enum
1011                {
1012                        WM_FIRST = WM_APP,
1013                        WM_FILTERGRAPHEVENT,
1014                };
1015
1016        private:
1017                CMainPropertySheet& m_Owner;
1018                CStatic m_VideoStatic;
1019                CGenericFilterGraph m_FilterGraph;
1020                CObjectPtr<CSourceFilter> m_pSourceFilter;
1021                CVmr7Window m_RendererWindow;
1022                CButton m_RunButton;
1023                CButton m_PauseButton;
1024                CButton m_StopButton;
1025                CButton m_WeaveButton;
1026                CButton m_ColorizeButton;
1027
1028                VOID UpdateControls()
1029                {
1030                        OAFilterState State;
1031                        if(SUCCEEDED(m_FilterGraph.m_pMediaControl->GetState(0, &State)))
1032                        {
1033                                m_RunButton.EnableWindow(State != State_Running);
1034                                m_PauseButton.EnableWindow(State != State_Paused);
1035                                m_StopButton.EnableWindow(State != State_Stopped);
1036                        } else
1037                        {
1038                                m_RunButton.EnableWindow(FALSE);
1039                                m_PauseButton.EnableWindow(FALSE);
1040                                m_StopButton.EnableWindow(FALSE);
1041                        }
1042                }
1043
1044        public:
1045        // CVmr7PropertyPage
1046                CVmr7PropertyPage(CMainPropertySheet* pOwner) :
1047                        m_Owner(*pOwner)
1048                {
1049                }
1050
1051        // CDialogResize
1052                VOID DlgResize_UpdateLayout(INT nWidth, INT nHeight)
1053                {
1054                        __super::DlgResize_UpdateLayout(nWidth, nHeight);
1055                        CRect VideoPosition;
1056                        _W(m_VideoStatic.GetWindowRect(VideoPosition));
1057                        _W(ScreenToClient(VideoPosition));
1058                        _W(m_RendererWindow.MoveWindow(VideoPosition));
1059                }
1060
1061        // Window Message Handlers
1062                LRESULT OnInitDialog(HWND, LPARAM)
1063                {
1064                        m_VideoStatic = GetDlgItem(IDC_MAIN_VMR7_VIDEO);
1065                        m_VideoStatic.ShowWindow(SW_HIDE);
1066                        CRect VideoPosition;
1067                        _W(m_VideoStatic.GetWindowRect(VideoPosition));
1068                        _W(ScreenToClient(VideoPosition));
1069                        m_RunButton = GetDlgItem(IDC_MAIN_VMR7_RUN);
1070                        m_PauseButton = GetDlgItem(IDC_MAIN_VMR7_PAUSE);
1071                        m_StopButton = GetDlgItem(IDC_MAIN_VMR7_STOP);
1072                        m_WeaveButton = GetDlgItem(IDC_MAIN_VMR7_WEAVE);
1073                        m_ColorizeButton = GetDlgItem(IDC_MAIN_VMR7_COLORIZE);
1074                        DlgResize_Init(TRUE);
1075                        m_FilterGraph.CoCreateInstance();
1076                        CObjectPtr<CAmGraphBuilderCallback> pAmGraphBuilderCallback;
1077                        pAmGraphBuilderCallback.Construct();
1078                        pAmGraphBuilderCallback->SetGraphBuilder(m_FilterGraph.m_pFilterGraph);
1079                        const CComPtr<IBaseFilter> pBaseFilter = m_RendererWindow.CoCreateBaseFilterInstance();
1080                        __C(m_FilterGraph->AddFilter(pBaseFilter, CT2CW(_T("VMR-7"))));
1081                        m_RendererWindow.Create(m_hWnd);
1082                        _W(m_RendererWindow.MoveWindow(VideoPosition));
1083                        m_RendererWindow.ShowWindow(SW_SHOWNORMAL);
1084                        m_RendererWindow.Initialize(pBaseFilter);
1085                        CObjectPtr<CSourceFilter> pSourceFilter;
1086                        pSourceFilter.Construct()->Initialize();
1087                        pSourceFilter->SetWeave(m_WeaveButton.GetCheck());
1088                        pSourceFilter->SetColorize(m_ColorizeButton.GetCheck());
1089                        m_pSourceFilter = pSourceFilter;
1090                        __C(m_FilterGraph->AddFilter(pSourceFilter, CT2CW(_T("Source"))));
1091                        __C(m_FilterGraph->Connect(pSourceFilter->GetOutputPin(), _FilterGraphHelper::GetFilterPin(m_RendererWindow.m_pBaseFilter)));
1092                        __C(m_FilterGraph.m_pMediaEventEx->SetNotifyWindow((OAHWND) m_hWnd, WM_FILTERGRAPHEVENT, (LONG_PTR) this));
1093                        UpdateControls();
1094                        return 0;
1095                }
1096                LRESULT OnDestroy()
1097                {
1098                        if(m_FilterGraph.m_pMediaControl)
1099                                _V(m_FilterGraph.m_pMediaControl->Stop());
1100                        m_RendererWindow.Terminate();
1101                        m_pSourceFilter.Release();
1102                        m_FilterGraph.Release();
1103                        return 0;
1104                }
1105                LRESULT OnRunButtonClicked(UINT, INT, HWND)
1106                {
1107                        CWaitCursor WaitCursor;
1108                        __D(m_FilterGraph.m_pMediaControl, E_NOINTERFACE);
1109                        __C(m_FilterGraph.m_pMediaControl->Run());
1110                        UpdateControls();
1111                        #pragma region Capabilities
1112                        _ATLTRY
1113                        {
1114                                const CComQIPtr<IVMRDeinterlaceControl> pVmrDeinterlaceControl = m_RendererWindow.m_pBaseFilter;
1115                                VMRVideoDesc VideoDescription;
1116                                ZeroMemory(&VideoDescription, sizeof VideoDescription);
1117                                VideoDescription.dwSize = sizeof VideoDescription;
1118                                const CVideoInfoHeader2* pVideoInfoHeader2 = m_pSourceFilter->GetRequestedMediaType().GetVideoInfoHeader2();
1119                                _A(pVideoInfoHeader2);
1120                                const CSize Extent = pVideoInfoHeader2->GetExtent();
1121                                VideoDescription.dwSampleWidth = Extent.cx;
1122                                VideoDescription.dwSampleHeight = Extent.cy;
1123                                VideoDescription.SingleFieldPerSample = FALSE;
1124                                VideoDescription.dwFourCC = pVideoInfoHeader2->GetBitmapInfoHeader().biCompression;
1125                                VideoDescription.InputSampleFreq.dwNumerator = 30000;
1126                                VideoDescription.InputSampleFreq.dwDenominator = 1001;
1127                                VideoDescription.OutputFrameFreq.dwNumerator = 60000;
1128                                VideoDescription.OutputFrameFreq.dwDenominator = 1001;
1129                                DWORD nModeCount = 16;
1130                                CTempBufferT<GUID> pModes(nModeCount);
1131                                const HRESULT nGetNumberOfDeinterlaceModesResult = pVmrDeinterlaceControl->GetNumberOfDeinterlaceModes(&VideoDescription, &nModeCount, pModes);
1132                                _Z4(atlTraceGeneral, 4, _T("nGetNumberOfDeinterlaceModesResult 0x%08x, nModeCount %d\n"), nGetNumberOfDeinterlaceModesResult, nModeCount);
1133                                if(SUCCEEDED(nGetNumberOfDeinterlaceModesResult))
1134                                {
1135                                        for(DWORD nModeIndex = 0; nModeIndex < nModeCount; nModeIndex++)
1136                                        {
1137                                                const GUID& Mode = pModes[nModeIndex];
1138                                                _Z4(atlTraceGeneral, 4, _T("nModeIndex %d, Mode %s\n"), nModeIndex, FormatDeinterlaceMode(Mode));
1139                                                VMRDeinterlaceCaps Capabilities;
1140                                                ZeroMemory(&Capabilities, sizeof Capabilities);
1141                                                Capabilities.dwSize = sizeof Capabilities;
1142                                                const HRESULT nGetDeinterlaceModeCapsResult = pVmrDeinterlaceControl->GetDeinterlaceModeCaps(const_cast<GUID*>(&Mode), &VideoDescription, &Capabilities);
1143                                                _Z4(atlTraceGeneral, 4, _T("nGetDeinterlaceModeCapsResult 0x%08x, Capabilities.dwNumPreviousOutputFrames %d, .dwNumForwardRefSamples %d, .dwNumBackwardRefSamples %d, .DeinterlaceTechnology 0x%x\n"), nGetDeinterlaceModeCapsResult, Capabilities.dwNumPreviousOutputFrames, Capabilities.dwNumForwardRefSamples, Capabilities.dwNumBackwardRefSamples, Capabilities.DeinterlaceTechnology);
1144                                        }
1145                                }
1146                                GUID DeinterlaceMode = GUID_NULL;
1147                                const HRESULT nGetDeinterlaceModeResult = pVmrDeinterlaceControl->GetDeinterlaceMode(0, &DeinterlaceMode);
1148                                _Z4(atlTraceGeneral, 4, _T("nGetDeinterlaceModeResult 0x%08x\n"), nGetDeinterlaceModeResult);
1149                                if(SUCCEEDED(nGetDeinterlaceModeResult) && !(nGetDeinterlaceModeResult == S_FALSE && DeinterlaceMode == GUID_NULL))
1150                                        _Z4(atlTraceGeneral, 4, _T("DeinterlaceMode %s\n"), FormatDeinterlaceMode(DeinterlaceMode));
1151                                DWORD nPreferences = 0;
1152                                const HRESULT nGetDeinterlacePrefsResult = pVmrDeinterlaceControl->GetDeinterlacePrefs(&nPreferences);
1153                                _Z4(atlTraceGeneral, 4, _T("nGetDeinterlacePrefsResult 0x%08x, nPreferences 0x%x\n"), nGetDeinterlacePrefsResult, nPreferences);
1154                                GUID ActualDeinterlaceMode;
1155                                const HRESULT nGetActualDeinterlaceModeResult = pVmrDeinterlaceControl->GetActualDeinterlaceMode(0, &ActualDeinterlaceMode);
1156                                _Z4(atlTraceGeneral, 4, _T("nGetActualDeinterlaceModeResult 0x%08x\n"), nGetActualDeinterlaceModeResult);
1157                                if(SUCCEEDED(nGetActualDeinterlaceModeResult))
1158                                        _Z4(atlTraceGeneral, 4, _T("ActualDeinterlaceMode %s\n"), FormatDeinterlaceMode(ActualDeinterlaceMode));
1159                        }
1160                        _ATLCATCHALL()
1161                        {
1162                                _Z_EXCEPTION();
1163                        }
1164                        #pragma endregion
1165                        return 0;
1166                }
1167                LRESULT OnPauseButtonClicked(UINT, INT, HWND)
1168                {
1169                        CWaitCursor WaitCursor;
1170                        __D(m_FilterGraph.m_pMediaControl, E_NOINTERFACE);
1171                        __C(m_FilterGraph.m_pMediaControl->Pause());
1172                        UpdateControls();
1173                        return 0;
1174                }
1175                LRESULT OnStopButtonClicked(UINT, INT, HWND)
1176                {
1177                        CWaitCursor WaitCursor;
1178                        if(m_FilterGraph.m_pMediaControl)
1179                                _V(m_FilterGraph.m_pMediaControl->Stop());
1180                        UpdateControls();
1181                        return 0;
1182                }
1183                LRESULT OnWeaveButtonClicked(UINT, INT, HWND)
1184                {
1185                        if(m_pSourceFilter)
1186                                m_pSourceFilter->SetWeave(m_WeaveButton.GetCheck());
1187                        return 0;
1188                }
1189                LRESULT OnColorizeButtonClicked(UINT, INT, HWND)
1190                {
1191                        if(m_pSourceFilter)
1192                                m_pSourceFilter->SetColorize(m_ColorizeButton.GetCheck());
1193                        return 0;
1194                }
1195                LRESULT OnFilterGraphEvent(UINT, WPARAM, LPARAM)
1196                {
1197                        if(!m_FilterGraph.m_pMediaEventEx)
1198                                return 0;
1199                        _ATLTRY
1200                        {
1201                                for(; ; )
1202                                {
1203                                        LONG nEventCode;
1204                                        LONG_PTR nParameter1, nParameter2;
1205                                        const HRESULT nGetEventResult = m_FilterGraph.m_pMediaEventEx->GetEvent(&nEventCode, &nParameter1, &nParameter2, 0);
1206                                        if(nGetEventResult == E_ABORT)
1207                                                break;
1208                                        __C(nGetEventResult);
1209                                        _ATLTRY
1210                                        {
1211                                                HandleMediaEvent(nEventCode, nParameter1, nParameter2);
1212                                        }
1213                                        _ATLCATCHALL()
1214                                        {
1215                                                _V(m_FilterGraph.m_pMediaEventEx->FreeEventParams(nEventCode, nParameter1, nParameter2));
1216                                                _ATLRETHROW;
1217                                        }
1218                                        _V(m_FilterGraph.m_pMediaEventEx->FreeEventParams(nEventCode, nParameter1, nParameter2));
1219                                }
1220                        }
1221                        _ATLCATCHALL()
1222                        {
1223                                _Z_EXCEPTION();
1224                        }
1225                        return 0;
1226                }
1227                INT OnKillActive()
1228                {
1229                        m_StopButton.Click();
1230                        return 0;
1231                }
1232        };
1233
1234        ////////////////////////////////////////////////////
1235        // CVmr9PropertyPage
1236
1237        class CVmr9PropertyPage :
1238                public CPropertyPageT<CVmr9PropertyPage>,
1239                public CDialogResize<CVmr9PropertyPage>,
1240                public CVrPropertyPageT<CVmr9PropertyPage>
1241        {
1242        public:
1243                enum { IDD = IDD_MAIN_VMR9 };
1244
1245        BEGIN_MSG_MAP_EX(CVmr9PropertyPage)
1246                CHAIN_MSG_MAP(CPropertyPageT<CVmr9PropertyPage>)
1247                CHAIN_MSG_MAP(CDialogResize<CVmr9PropertyPage>)
1248                MSG_WM_INITDIALOG(OnInitDialog)
1249                MSG_WM_DESTROY(OnDestroy)
1250                COMMAND_ID_HANDLER_EX(IDC_MAIN_VMR9_RUN, OnRunButtonClicked)
1251                COMMAND_ID_HANDLER_EX(IDC_MAIN_VMR9_PAUSE, OnPauseButtonClicked)
1252                COMMAND_ID_HANDLER_EX(IDC_MAIN_VMR9_STOP, OnStopButtonClicked)
1253                COMMAND_ID_HANDLER_EX(IDC_MAIN_VMR9_WEAVE, OnWeaveButtonClicked)
1254                COMMAND_ID_HANDLER_EX(IDC_MAIN_VMR9_COLORIZE, OnColorizeButtonClicked)
1255                MESSAGE_HANDLER_EX(WM_FILTERGRAPHEVENT, OnFilterGraphEvent)
1256                REFLECT_NOTIFICATIONS()
1257        END_MSG_MAP()
1258
1259        BEGIN_DLGRESIZE_MAP(CVmr9PropertyPage)
1260                DLGRESIZE_CONTROL(IDC_MAIN_VMR9_VIDEO, DLSZ_SIZE_X | DLSZ_SIZE_Y)
1261                DLGRESIZE_CONTROL(IDC_MAIN_VMR9_RUN, DLSZ_MOVE_X)
1262                DLGRESIZE_CONTROL(IDC_MAIN_VMR9_PAUSE, DLSZ_MOVE_X)
1263                DLGRESIZE_CONTROL(IDC_MAIN_VMR9_STOP, DLSZ_MOVE_X)
1264                DLGRESIZE_CONTROL(IDC_MAIN_VMR9_WEAVE, DLSZ_MOVE_Y)
1265                DLGRESIZE_CONTROL(IDC_MAIN_VMR9_COLORIZE, DLSZ_MOVE_Y)
1266        END_DLGRESIZE_MAP()
1267
1268        public:
1269
1270                ////////////////////////////////////////////////////////
1271                // Window Message Identifiers
1272
1273                enum
1274                {
1275                        WM_FIRST = WM_APP,
1276                        WM_FILTERGRAPHEVENT,
1277                };
1278
1279        private:
1280                CMainPropertySheet& m_Owner;
1281                CStatic m_VideoStatic;
1282                CGenericFilterGraph m_FilterGraph;
1283                CObjectPtr<CSourceFilter> m_pSourceFilter;
1284                CVmr9Window m_RendererWindow;
1285                CButton m_RunButton;
1286                CButton m_PauseButton;
1287                CButton m_StopButton;
1288                CButton m_WeaveButton;
1289                CButton m_ColorizeButton;
1290
1291                VOID UpdateControls()
1292                {
1293                        OAFilterState State;
1294                        if(SUCCEEDED(m_FilterGraph.m_pMediaControl->GetState(0, &State)))
1295                        {
1296                                m_RunButton.EnableWindow(State != State_Running);
1297                                m_PauseButton.EnableWindow(State != State_Paused);
1298                                m_StopButton.EnableWindow(State != State_Stopped);
1299                        } else
1300                        {
1301                                m_RunButton.EnableWindow(FALSE);
1302                                m_PauseButton.EnableWindow(FALSE);
1303                                m_StopButton.EnableWindow(FALSE);
1304                        }
1305                }
1306
1307        public:
1308        // CVmr9PropertyPage
1309                CVmr9PropertyPage(CMainPropertySheet* pOwner) :
1310                        m_Owner(*pOwner)
1311                {
1312                }
1313
1314        // CDialogResize
1315                VOID DlgResize_UpdateLayout(INT nWidth, INT nHeight)
1316                {
1317                        __super::DlgResize_UpdateLayout(nWidth, nHeight);
1318                        CRect VideoPosition;
1319                        _W(m_VideoStatic.GetWindowRect(VideoPosition));
1320                        _W(ScreenToClient(VideoPosition));
1321                        _W(m_RendererWindow.MoveWindow(VideoPosition));
1322                }
1323
1324        // Window Message Handlers
1325                LRESULT OnInitDialog(HWND, LPARAM)
1326                {
1327                        m_VideoStatic = GetDlgItem(IDC_MAIN_VMR9_VIDEO);
1328                        m_VideoStatic.ShowWindow(SW_HIDE);
1329                        CRect VideoPosition;
1330                        _W(m_VideoStatic.GetWindowRect(VideoPosition));
1331                        _W(ScreenToClient(VideoPosition));
1332                        m_RunButton = GetDlgItem(IDC_MAIN_VMR9_RUN);
1333                        m_PauseButton = GetDlgItem(IDC_MAIN_VMR9_PAUSE);
1334                        m_StopButton = GetDlgItem(IDC_MAIN_VMR9_STOP);
1335                        m_WeaveButton = GetDlgItem(IDC_MAIN_VMR9_WEAVE);
1336                        m_ColorizeButton = GetDlgItem(IDC_MAIN_VMR9_COLORIZE);
1337                        DlgResize_Init(TRUE);
1338                        m_FilterGraph.CoCreateInstance();
1339                        CObjectPtr<CAmGraphBuilderCallback> pAmGraphBuilderCallback;
1340                        pAmGraphBuilderCallback.Construct();
1341                        pAmGraphBuilderCallback->SetGraphBuilder(m_FilterGraph.m_pFilterGraph);
1342                        const CComPtr<IBaseFilter> pBaseFilter = m_RendererWindow.CoCreateBaseFilterInstance();
1343                        __C(m_FilterGraph->AddFilter(pBaseFilter, CT2CW(_T("VMR-9"))));
1344                        m_RendererWindow.Create(m_hWnd);
1345                        _W(m_RendererWindow.MoveWindow(VideoPosition));
1346                        m_RendererWindow.ShowWindow(SW_SHOWNORMAL);
1347                        m_RendererWindow.Initialize(pBaseFilter);
1348                        CObjectPtr<CSourceFilter> pSourceFilter;
1349                        pSourceFilter.Construct()->Initialize();
1350                        pSourceFilter->SetWeave(m_WeaveButton.GetCheck());
1351                        pSourceFilter->SetColorize(m_ColorizeButton.GetCheck());
1352                        m_pSourceFilter = pSourceFilter;
1353                        __C(m_FilterGraph->AddFilter(pSourceFilter, CT2CW(_T("Source"))));
1354                        __C(m_FilterGraph->Connect(pSourceFilter->GetOutputPin(), _FilterGraphHelper::GetFilterPin(m_RendererWindow.m_pBaseFilter)));
1355                        __C(m_FilterGraph.m_pMediaEventEx->SetNotifyWindow((OAHWND) m_hWnd, WM_FILTERGRAPHEVENT, (LONG_PTR) this));
1356                        #pragma region Simulate EC_DISPLAY_CHANGED (Development)
1357                        #if _DEVELOPMENT && FALSE
1358                                __C(m_FilterGraph.m_pMediaEventEx->CancelDefaultHandling(EC_DISPLAY_CHANGED));
1359                                _W(GetParent().SetWindowPos(NULL, 1680 + 100, 100, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE));
1360                                CRect RendererPosition;
1361                                _W(m_RendererWindow.GetWindowRect(RendererPosition));
1362                                CVmr9Window::CMonitorInformation MonitorInformation(pBaseFilter);
1363                                UINT nMonitor;
1364                                if(MonitorInformation.SuggestMonitor(RendererPosition, nMonitor))
1365                                {
1366                                        _Z4(atlTraceGeneral, 4, _T("nMonitor %d\n"), nMonitor);
1367                                        _A(MonitorInformation.m_pVmrMonitorConfig->SetMonitor(nMonitor) == VFW_E_WRONG_STATE);
1368                                        const CComPtr<IPin> pInputPin = _FilterGraphHelper::GetFilterPin(pBaseFilter, PINDIR_INPUT);
1369                                        const CComPtr<IPin> pOutputPin = _FilterGraphHelper::GetPeerPin(pInputPin);
1370                                        __D(pInputPin && pOutputPin, E_NOINTERFACE);
1371                                        const CMediaType pMediaType = _FilterGraphHelper::GetPinMediaType(pOutputPin);
1372                                        __C(m_FilterGraph.Disconnect(pOutputPin));
1373                                        __C(m_FilterGraph.Disconnect(pInputPin));
1374                                        const HRESULT nSetMonitorResult = MonitorInformation.m_pVmrMonitorConfig->SetMonitor(nMonitor);
1375                                        _Z45_DSHRESULT(nSetMonitorResult);
1376                                        m_RendererWindow.UpdateVideoPosition();
1377                                        const HRESULT nConnectResult = m_FilterGraph.ConnectDirect(pOutputPin, pInputPin, pMediaType);
1378                                        _Z45_DSHRESULT(nConnectResult);
1379                                        if(FAILED(nConnectResult))
1380                                                __C(m_FilterGraph.Connect(pOutputPin, pInputPin));
1381                                }
1382                        #endif // _DEVELOPMENT
1383                        #pragma endregion
1384                        UpdateControls();
1385                        return 0;
1386                }
1387                LRESULT OnDestroy()
1388                {
1389                        if(m_FilterGraph.m_pMediaControl)
1390                                _V(m_FilterGraph.m_pMediaControl->Stop());
1391                        m_RendererWindow.Terminate();
1392                        m_pSourceFilter.Release();
1393                        m_FilterGraph.Release();
1394                        return 0;
1395                }
1396                LRESULT OnRunButtonClicked(UINT, INT, HWND)
1397                {
1398                        CWaitCursor WaitCursor;
1399                        __D(m_FilterGraph.m_pMediaControl, E_NOINTERFACE);
1400                        __C(m_FilterGraph.m_pMediaControl->Run());
1401                        UpdateControls();
1402                        #pragma region Capabilities
1403                        _ATLTRY
1404                        {
1405                                const CComQIPtr<IVMRDeinterlaceControl9> pVmrDeinterlaceControl9 = m_RendererWindow.m_pBaseFilter;
1406                                VMR9VideoDesc VideoDescription;
1407                                ZeroMemory(&VideoDescription, sizeof VideoDescription);
1408                                VideoDescription.dwSize = sizeof VideoDescription;
1409                                const CVideoInfoHeader2* pVideoInfoHeader2 = m_pSourceFilter->GetRequestedMediaType().GetVideoInfoHeader2();
1410                                _A(pVideoInfoHeader2);
1411                                const CSize Extent = pVideoInfoHeader2->GetExtent();
1412                                VideoDescription.dwSampleWidth = Extent.cx;
1413                                VideoDescription.dwSampleHeight = Extent.cy;
1414                                VideoDescription.SampleFormat = VMR9_SampleFieldInterleavedEvenFirst;
1415                                VideoDescription.dwFourCC = pVideoInfoHeader2->GetBitmapInfoHeader().biCompression;
1416                                VideoDescription.InputSampleFreq.dwNumerator = 30000;
1417                                VideoDescription.InputSampleFreq.dwDenominator = 1001;
1418                                VideoDescription.OutputFrameFreq.dwNumerator = 60000;
1419                                VideoDescription.OutputFrameFreq.dwDenominator = 1001;
1420                                DWORD nModeCount = 16;
1421                                CTempBufferT<GUID> pModes(nModeCount);
1422                                const HRESULT nGetNumberOfDeinterlaceModesResult = pVmrDeinterlaceControl9->GetNumberOfDeinterlaceModes(&VideoDescription, &nModeCount, pModes);
1423                                _Z4(atlTraceGeneral, 4, _T("nGetNumberOfDeinterlaceModesResult 0x%08x, nModeCount %d\n"), nGetNumberOfDeinterlaceModesResult, nModeCount);
1424                                if(SUCCEEDED(nGetNumberOfDeinterlaceModesResult))
1425                                {
1426                                        for(DWORD nModeIndex = 0; nModeIndex < nModeCount; nModeIndex++)
1427                                        {
1428                                                const GUID& Mode = pModes[nModeIndex];
1429                                                _Z4(atlTraceGeneral, 4, _T("nModeIndex %d, Mode %s\n"), nModeIndex, FormatDeinterlaceMode(Mode));
1430                                                VMR9DeinterlaceCaps Capabilities;
1431                                                ZeroMemory(&Capabilities, sizeof Capabilities);
1432                                                Capabilities.dwSize = sizeof Capabilities;
1433                                                const HRESULT nGetDeinterlaceModeCapsResult = pVmrDeinterlaceControl9->GetDeinterlaceModeCaps(const_cast<GUID*>(&Mode), &VideoDescription, &Capabilities);
1434                                                _Z4(atlTraceGeneral, 4, _T("nGetDeinterlaceModeCapsResult 0x%08x, Capabilities.dwNumPreviousOutputFrames %d, .dwNumForwardRefSamples %d, .dwNumBackwardRefSamples %d, .DeinterlaceTechnology 0x%x\n"), nGetDeinterlaceModeCapsResult, Capabilities.dwNumPreviousOutputFrames, Capabilities.dwNumForwardRefSamples, Capabilities.dwNumBackwardRefSamples, Capabilities.DeinterlaceTechnology);
1435                                        }
1436                                }
1437                                GUID DeinterlaceMode = GUID_NULL;
1438                                const HRESULT nGetDeinterlaceModeResult = pVmrDeinterlaceControl9->GetDeinterlaceMode(0, &DeinterlaceMode);
1439                                _Z4(atlTraceGeneral, 4, _T("nGetDeinterlaceModeResult 0x%08x\n"), nGetDeinterlaceModeResult);
1440                                if(SUCCEEDED(nGetDeinterlaceModeResult) && !(nGetDeinterlaceModeResult == S_FALSE && DeinterlaceMode == GUID_NULL))
1441                                        _Z4(atlTraceGeneral, 4, _T("DeinterlaceMode %s\n"), FormatDeinterlaceMode(DeinterlaceMode));
1442                                DWORD nPreferences = 0;
1443                                const HRESULT nGetDeinterlacePrefsResult = pVmrDeinterlaceControl9->GetDeinterlacePrefs(&nPreferences);
1444                                _Z4(atlTraceGeneral, 4, _T("nGetDeinterlacePrefsResult 0x%08x, nPreferences 0x%x\n"), nGetDeinterlacePrefsResult, nPreferences);
1445                                GUID ActualDeinterlaceMode;
1446                                const HRESULT nGetActualDeinterlaceModeResult = pVmrDeinterlaceControl9->GetActualDeinterlaceMode(0, &ActualDeinterlaceMode);
1447                                _Z4(atlTraceGeneral, 4, _T("nGetActualDeinterlaceModeResult 0x%08x\n"), nGetActualDeinterlaceModeResult);
1448                                if(SUCCEEDED(nGetActualDeinterlaceModeResult))
1449                                        _Z4(atlTraceGeneral, 4, _T("ActualDeinterlaceMode %s\n"), FormatDeinterlaceMode(ActualDeinterlaceMode));
1450                        }
1451                        _ATLCATCHALL()
1452                        {
1453                                _Z_EXCEPTION();
1454                        }
1455                        #pragma endregion
1456                        return 0;
1457                }
1458                LRESULT OnPauseButtonClicked(UINT, INT, HWND)
1459                {
1460                        CWaitCursor WaitCursor;
1461                        __D(m_FilterGraph.m_pMediaControl, E_NOINTERFACE);
1462                        __C(m_FilterGraph.m_pMediaControl->Pause());
1463                        UpdateControls();
1464                        return 0;
1465                }
1466                LRESULT OnStopButtonClicked(UINT, INT, HWND)
1467                {
1468                        CWaitCursor WaitCursor;
1469                        if(m_FilterGraph.m_pMediaControl)
1470                                _V(m_FilterGraph.m_pMediaControl->Stop());
1471                        UpdateControls();
1472                        return 0;
1473                }
1474                LRESULT OnWeaveButtonClicked(UINT, INT, HWND)
1475                {
1476                        if(m_pSourceFilter)
1477                                m_pSourceFilter->SetWeave(m_WeaveButton.GetCheck());
1478                        return 0;
1479                }
1480                LRESULT OnColorizeButtonClicked(UINT, INT, HWND)
1481                {
1482                        if(m_pSourceFilter)
1483                                m_pSourceFilter->SetColorize(m_ColorizeButton.GetCheck());
1484                        return 0;
1485                }
1486                LRESULT OnFilterGraphEvent(UINT, WPARAM, LPARAM)
1487                {
1488                        if(!m_FilterGraph.m_pMediaEventEx)
1489                                return 0;
1490                        _ATLTRY
1491                        {
1492                                for(; ; )
1493                                {
1494                                        LONG nEventCode;
1495                                        LONG_PTR nParameter1, nParameter2;
1496                                        const HRESULT nGetEventResult = m_FilterGraph.m_pMediaEventEx->GetEvent(&nEventCode, &nParameter1, &nParameter2, 0);
1497                                        if(nGetEventResult == E_ABORT)
1498                                                break;
1499                                        __C(nGetEventResult);
1500                                        _ATLTRY
1501                                        {
1502                                                HandleMediaEvent(nEventCode, nParameter1, nParameter2);
1503                                        }
1504                                        _ATLCATCHALL()
1505                                        {
1506                                                _V(m_FilterGraph.m_pMediaEventEx->FreeEventParams(nEventCode, nParameter1, nParameter2));
1507                                                _ATLRETHROW;
1508                                        }
1509                                        _V(m_FilterGraph.m_pMediaEventEx->FreeEventParams(nEventCode, nParameter1, nParameter2));
1510                                }
1511                        }
1512                        _ATLCATCHALL()
1513                        {
1514                                _Z_EXCEPTION();
1515                        }
1516                        return 0;
1517                }
1518                INT OnKillActive()
1519                {
1520                        m_StopButton.Click();
1521                        return 0;
1522                }
1523        };
1524
1525        ////////////////////////////////////////////////////
1526        // CEvrPropertyPage
1527
1528        class CEvrPropertyPage :
1529                public CPropertyPageT<CEvrPropertyPage>,
1530                public CDialogResize<CEvrPropertyPage>,
1531                public CVrPropertyPageT<CEvrPropertyPage>
1532        {
1533        public:
1534                enum { IDD = IDD_MAIN_EVR };
1535
1536        BEGIN_MSG_MAP_EX(CEvrPropertyPage)
1537                CHAIN_MSG_MAP(CPropertyPageT<CEvrPropertyPage>)
1538                CHAIN_MSG_MAP(CDialogResize<CEvrPropertyPage>)
1539                MSG_WM_INITDIALOG(OnInitDialog)
1540                MSG_WM_DESTROY(OnDestroy)
1541                COMMAND_ID_HANDLER_EX(IDC_MAIN_EVR_RUN, OnRunButtonClicked)
1542                COMMAND_ID_HANDLER_EX(IDC_MAIN_EVR_PAUSE, OnPauseButtonClicked)
1543                COMMAND_ID_HANDLER_EX(IDC_MAIN_EVR_STOP, OnStopButtonClicked)
1544                COMMAND_ID_HANDLER_EX(IDC_MAIN_EVR_WEAVE, OnWeaveButtonClicked)
1545                COMMAND_ID_HANDLER_EX(IDC_MAIN_EVR_COLORIZE, OnColorizeButtonClicked)
1546                MESSAGE_HANDLER_EX(WM_FILTERGRAPHEVENT, OnFilterGraphEvent)
1547                REFLECT_NOTIFICATIONS()
1548        END_MSG_MAP()
1549
1550        BEGIN_DLGRESIZE_MAP(CEvrPropertyPage)
1551                DLGRESIZE_CONTROL(IDC_MAIN_EVR_VIDEO, DLSZ_SIZE_X | DLSZ_SIZE_Y)
1552                DLGRESIZE_CONTROL(IDC_MAIN_EVR_RUN, DLSZ_MOVE_X)
1553                DLGRESIZE_CONTROL(IDC_MAIN_EVR_PAUSE, DLSZ_MOVE_X)
1554                DLGRESIZE_CONTROL(IDC_MAIN_EVR_STOP, DLSZ_MOVE_X)
1555                DLGRESIZE_CONTROL(IDC_MAIN_EVR_WEAVE, DLSZ_MOVE_Y)
1556                DLGRESIZE_CONTROL(IDC_MAIN_EVR_COLORIZE, DLSZ_MOVE_Y)
1557        END_DLGRESIZE_MAP()
1558
1559        public:
1560
1561                ////////////////////////////////////////////////////////
1562                // Window Message Identifiers
1563
1564                enum
1565                {
1566                        WM_FIRST = WM_APP,
1567                        WM_FILTERGRAPHEVENT,
1568                };
1569
1570        private:
1571                CMainPropertySheet& m_Owner;
1572                CStatic m_VideoStatic;
1573                CGenericFilterGraph m_FilterGraph;
1574                CObjectPtr<CSourceFilter> m_pSourceFilter;
1575                CEvrWindow m_RendererWindow;
1576                CButton m_RunButton;
1577                CButton m_PauseButton;
1578                CButton m_StopButton;
1579                CButton m_WeaveButton;
1580                CButton m_ColorizeButton;
1581
1582                VOID UpdateControls()
1583                {
1584                        OAFilterState State;
1585                        if(SUCCEEDED(m_FilterGraph.m_pMediaControl->GetState(0, &State)))
1586                        {
1587                                m_RunButton.EnableWindow(State != State_Running);
1588                                m_PauseButton.EnableWindow(State != State_Paused);
1589                                m_StopButton.EnableWindow(State != State_Stopped);
1590                        } else
1591                        {
1592                                m_RunButton.EnableWindow(FALSE);
1593                                m_PauseButton.EnableWindow(FALSE);
1594                                m_StopButton.EnableWindow(FALSE);
1595                        }
1596                }
1597
1598        public:
1599        // CEvrPropertyPage
1600                CEvrPropertyPage(CMainPropertySheet* pOwner) :
1601                        m_Owner(*pOwner)
1602                {
1603                }
1604
1605        // CDialogResize
1606                VOID DlgResize_UpdateLayout(INT nWidth, INT nHeight)
1607                {
1608                        __super::DlgResize_UpdateLayout(nWidth, nHeight);
1609                        CRect VideoPosition;
1610                        _W(m_VideoStatic.GetWindowRect(VideoPosition));
1611                        _W(ScreenToClient(VideoPosition));
1612                        _W(m_RendererWindow.MoveWindow(VideoPosition));
1613                }
1614
1615        // Window Message Handlers
1616                LRESULT OnInitDialog(HWND, LPARAM)
1617                {
1618                        m_VideoStatic = GetDlgItem(IDC_MAIN_EVR_VIDEO);
1619                        m_VideoStatic.ShowWindow(SW_HIDE);
1620                        CRect VideoPosition;
1621                        _W(m_VideoStatic.GetWindowRect(VideoPosition));
1622                        _W(ScreenToClient(VideoPosition));
1623                        m_RunButton = GetDlgItem(IDC_MAIN_EVR_RUN);
1624                        m_PauseButton = GetDlgItem(IDC_MAIN_EVR_PAUSE);
1625                        m_StopButton = GetDlgItem(IDC_MAIN_EVR_STOP);
1626                        m_WeaveButton = GetDlgItem(IDC_MAIN_EVR_WEAVE);
1627                        m_ColorizeButton = GetDlgItem(IDC_MAIN_EVR_COLORIZE);
1628                        DlgResize_Init(TRUE);
1629                        m_FilterGraph.CoCreateInstance();
1630                        CObjectPtr<CAmGraphBuilderCallback> pAmGraphBuilderCallback;
1631                        pAmGraphBuilderCallback.Construct();
1632                        pAmGraphBuilderCallback->SetGraphBuilder(m_FilterGraph.m_pFilterGraph);
1633                        const CComPtr<IBaseFilter> pBaseFilter = m_RendererWindow.CoCreateBaseFilterInstance();
1634                        __C(m_FilterGraph->AddFilter(pBaseFilter, CT2CW(_T("EVR"))));
1635                        m_RendererWindow.Create(m_hWnd);
1636                        _W(m_RendererWindow.MoveWindow(VideoPosition));
1637                        m_RendererWindow.ShowWindow(SW_SHOWNORMAL);
1638                        m_RendererWindow.Initialize(pBaseFilter);
1639                        CObjectPtr<CSourceFilter> pSourceFilter;
1640                        pSourceFilter.Construct()->Initialize();
1641                        pSourceFilter->SetWeave(m_WeaveButton.GetCheck());
1642                        pSourceFilter->SetColorize(m_ColorizeButton.GetCheck());
1643                        m_pSourceFilter = pSourceFilter;
1644                        __C(m_FilterGraph->AddFilter(pSourceFilter, CT2CW(_T("Source"))));
1645                        __C(m_FilterGraph->Connect(pSourceFilter->GetOutputPin(), _FilterGraphHelper::GetFilterPin(m_RendererWindow.m_pBaseFilter)));
1646                        __C(m_FilterGraph.m_pMediaEventEx->SetNotifyWindow((OAHWND) m_hWnd, WM_FILTERGRAPHEVENT, (LONG_PTR) this));
1647                        UpdateControls();
1648                        return 0;
1649                }
1650                LRESULT OnDestroy()
1651                {
1652                        if(m_FilterGraph.m_pMediaControl)
1653                                _V(m_FilterGraph.m_pMediaControl->Stop());
1654                        m_RendererWindow.Terminate();
1655                        m_pSourceFilter.Release();
1656                        m_FilterGraph.Release();
1657                        return 0;
1658                }
1659                LRESULT OnRunButtonClicked(UINT, INT, HWND)
1660                {
1661                        CWaitCursor WaitCursor;
1662                        __D(m_FilterGraph.m_pMediaControl, E_NOINTERFACE);
1663                        __C(m_FilterGraph.m_pMediaControl->Run());
1664                        UpdateControls();
1665                        #pragma region Capabilities
1666                        _ATLTRY
1667                        {
1668                                const CComQIPtr<IMFGetService> pMfGetService = m_RendererWindow.m_pBaseFilter;
1669                                __D(pMfGetService, E_NOINTERFACE);
1670                                CComQIPtr<IMFVideoProcessor> pMfVideoProcessor;
1671                                __C(pMfGetService->GetService(MR_VIDEO_MIXER_SERVICE, __uuidof(IMFVideoProcessor), (VOID**) &pMfVideoProcessor));
1672                                __D(pMfVideoProcessor, E_NOINTERFACE);
1673                                UINT nModeCount = 0;
1674                                CComHeapPtr<GUID> pModes;
1675                                const HRESULT nGetAvailableVideoProcessorModesResult = pMfVideoProcessor->GetAvailableVideoProcessorModes(&nModeCount, &pModes);
1676                                _Z4(atlTraceGeneral, 4, _T("nGetAvailableVideoProcessorModesResult 0x%08x, nModeCount %d\n"), nGetAvailableVideoProcessorModesResult, nModeCount);
1677                                if(SUCCEEDED(nGetAvailableVideoProcessorModesResult))
1678                                {
1679                                        for(DWORD nModeIndex = 0; nModeIndex < nModeCount; nModeIndex++)
1680                                        {
1681                                                const GUID& Mode = pModes[nModeIndex];
1682                                                _Z4(atlTraceGeneral, 4, _T("nModeIndex %d, Mode %s\n"), nModeIndex, FormatDeinterlaceMode(Mode));
1683                                                DXVA2_VideoProcessorCaps Capabilities;
1684                                                ZeroMemory(&Capabilities, sizeof Capabilities);
1685                                                const HRESULT nGetVideoProcessorCapsResult = pMfVideoProcessor->GetVideoProcessorCaps(const_cast<GUID*>(&Mode), &Capabilities);
1686                                                _Z4(atlTraceGeneral, 4, _T("nGetVideoProcessorCapsResult 0x%08x") _T(", ") 
1687                                                        _T("Capabilities") 
1688                                                        _T(".NumForwardRefSamples %d") _T(", ") 
1689                                                        _T(".NumBackwardRefSamples %d") _T(", ") 
1690                                                        _T(".DeinterlaceTechnology %d") _T(", ") 
1691                                                        _T(".ProcAmpControlCaps %d") _T(", ") 
1692                                                        _T(".VideoProcessorOperations %d") _T(", ") 
1693                                                        _T(".NoiseFilterTechnology %d") _T(", ") 
1694                                                        _T(".DetailFilterTechnology %d") _T(", ") 
1695                                                        _T("\n"), 
1696                                                        nGetVideoProcessorCapsResult, 
1697                                                        Capabilities.DeviceCaps,
1698                                                        //Capabilities.InputPool,
1699                                                        Capabilities.NumForwardRefSamples,
1700                                                        Capabilities.NumBackwardRefSamples,
1701                                                        Capabilities.DeinterlaceTechnology,
1702                                                        Capabilities.ProcAmpControlCaps,
1703                                                        Capabilities.VideoProcessorOperations,
1704                                                        Capabilities.NoiseFilterTechnology,
1705                                                        Capabilities.DetailFilterTechnology,
1706                                                        0);
1707                                        }
1708                                }
1709                                GUID Mode = GUID_NULL;
1710                                const HRESULT nGetVideoProcessorModeResult = pMfVideoProcessor->GetVideoProcessorMode(&Mode);
1711                                _Z4(atlTraceGeneral, 4, _T("nGetVideoProcessorModeResult 0x%08x\n"), nGetVideoProcessorModeResult);
1712                                if(SUCCEEDED(nGetVideoProcessorModeResult) && !(nGetVideoProcessorModeResult == S_FALSE && Mode == GUID_NULL))
1713                                        _Z4(atlTraceGeneral, 4, _T("Mode %s\n"), FormatDeinterlaceMode(Mode));
1714                        }
1715                        _ATLCATCHALL()
1716                        {
1717                                _Z_EXCEPTION();
1718                        }
1719                        #pragma endregion
1720                        return 0;
1721                }
1722                LRESULT OnPauseButtonClicked(UINT, INT, HWND)
1723                {
1724                        CWaitCursor WaitCursor;
1725                        __D(m_FilterGraph.m_pMediaControl, E_NOINTERFACE);
1726                        __C(m_FilterGraph.m_pMediaControl->Pause());
1727                        UpdateControls();
1728                        return 0;
1729                }
1730                LRESULT OnStopButtonClicked(UINT, INT, HWND)
1731                {
1732                        CWaitCursor WaitCursor;
1733                        if(m_FilterGraph.m_pMediaControl)
1734                                _V(m_FilterGraph.m_pMediaControl->Stop());
1735                        UpdateControls();
1736                        return 0;
1737                }
1738                LRESULT OnWeaveButtonClicked(UINT, INT, HWND)
1739                {
1740                        if(m_pSourceFilter)
1741                                m_pSourceFilter->SetWeave(m_WeaveButton.GetCheck());
1742                        return 0;
1743                }
1744                LRESULT OnColorizeButtonClicked(UINT, INT, HWND)
1745                {
1746                        if(m_pSourceFilter)
1747                                m_pSourceFilter->SetColorize(m_ColorizeButton.GetCheck());
1748                        return 0;
1749                }
1750                LRESULT OnFilterGraphEvent(UINT, WPARAM, LPARAM)
1751                {
1752                        if(!m_FilterGraph.m_pMediaEventEx)
1753                                return 0;
1754                        _ATLTRY
1755                        {
1756                                for(; ; )
1757                                {
1758                                        LONG nEventCode;
1759                                        LONG_PTR nParameter1, nParameter2;
1760                                        const HRESULT nGetEventResult = m_FilterGraph.m_pMediaEventEx->GetEvent(&nEventCode, &nParameter1, &nParameter2, 0);
1761                                        if(nGetEventResult == E_ABORT)
1762                                                break;
1763                                        __C(nGetEventResult);
1764                                        _ATLTRY
1765                                        {
1766                                                HandleMediaEvent(nEventCode, nParameter1, nParameter2);
1767                                        }
1768                                        _ATLCATCHALL()
1769                                        {
1770                                                _V(m_FilterGraph.m_pMediaEventEx->FreeEventParams(nEventCode, nParameter1, nParameter2));
1771                                                _ATLRETHROW;
1772                                        }
1773                                        _V(m_FilterGraph.m_pMediaEventEx->FreeEventParams(nEventCode, nParameter1, nParameter2));
1774                                }
1775                        }
1776                        _ATLCATCHALL()
1777                        {
1778                                _Z_EXCEPTION();
1779                        }
1780                        return 0;
1781                }
1782                INT OnKillActive()
1783                {
1784                        m_StopButton.Click();
1785                        return 0;
1786                }
1787        };
1788
1789public:
1790        CVmr7PropertyPage m_Vmr7PropertyPage;
1791        CVmr9PropertyPage m_Vmr9PropertyPage;
1792        CEvrPropertyPage m_EvrPropertyPage;
1793
1794public:
1795// CMainPropertySheet
1796        CMainPropertySheet() :
1797                CSizablePropertySheetT<CMainPropertySheet>(_T("Render Interlaced Video")),
1798                m_Vmr7PropertyPage(this),
1799                m_Vmr9PropertyPage(this),
1800                m_EvrPropertyPage(this)
1801        {
1802                AddPage(m_Vmr7PropertyPage);
1803                AddPage(m_Vmr9PropertyPage);
1804                AddPage(m_EvrPropertyPage);
1805        }
1806        BOOL SetInitialPosition()
1807        {
1808                if(!__super::SetInitialPosition())
1809                        return FALSE;
1810                _W(PostMessage(WM_SETLARGERINITIALPOSITION));
1811                return TRUE;
1812        }
1813        static CString FormatDeinterlaceMode(const GUID& DeinterlaceMode)
1814        {
1815                // NOTE: Windows SDK does not provide a linkable identifier...
1816                #pragma region VMR-7/9
1817                struct __declspec(uuid("{335aa36e-7884-43a4-9c91-7f87faf3e37e}")) DXVA_DeinterlaceBobDevice;
1818                struct __declspec(uuid("{0e85cb93-3046-4ff0-aecc-d58cb5f035fd}")) DXVA_DeinterlaceContainerDevice;
1819                if(DeinterlaceMode == __uuidof(DXVA_DeinterlaceBobDevice))
1820                        return _T("DXVA_DeinterlaceBobDevice");
1821                if(DeinterlaceMode == __uuidof(DXVA_DeinterlaceContainerDevice))
1822                        return _T("DXVA_DeinterlaceContainerDevice");
1823                #pragma endregion
1824                #pragma region EVR, DXVA2
1825                struct __declspec(uuid("{5a54a0c9-c7ec-4bd9-8ede-f3c75dc4393b}")) DXVA2_VideoProcProgressiveDevice;
1826                struct __declspec(uuid("{335aa36e-7884-43a4-9c91-7f87faf3e37e}")) DXVA2_VideoProcBobDevice;
1827                struct __declspec(uuid("{4553d47f-ee7e-4e3f-9475-dbf1376c4810}")) DXVA2_VideoProcSoftwareDevice;
1828                if(DeinterlaceMode == __uuidof(DXVA2_VideoProcProgressiveDevice))
1829                        return _T("DXVA2_VideoProcProgressiveDevice");
1830                if(DeinterlaceMode == __uuidof(DXVA2_VideoProcBobDevice))
1831                        return _T("DXVA2_VideoProcBobDevice");
1832                if(DeinterlaceMode == __uuidof(DXVA2_VideoProcSoftwareDevice))
1833                        return _T("DXVA2_VideoProcSoftwareDevice");
1834                return CString(_PersistHelper::StringFromIdentifier(DeinterlaceMode));
1835        }
1836
1837// Window Message Handlers
1838        LRESULT OnSetLargerInitialPosition(UINT, WPARAM, LPARAM)
1839        {
1840                CRect Position;
1841                _W(GetWindowRect(Position));
1842                Position.right += Position.Width();
1843                Position.bottom += Position.Height() / 4;
1844                _W(SetWindowPos(NULL, Position, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE));
1845                _W(CenterWindow());
1846                return 0;
1847        }
1848};
Note: See TracBrowser for help on using the repository browser.