source: trunk/Utilities/CaptureClock/MainDialog.h @ 104

Last change on this file since 104 was 104, checked in by roman, 11 years ago
  • Property svn:keywords set to Id
File size: 21.7 KB
Line 
1////////////////////////////////////////////////////////////
2// Copyright (C) Roman Ryltsov, 2012
3// Created by Roman Ryltsov roman@alax.info
4//
5// $Id: MainDialog.h 104 2012-08-26 13:39:30Z roman $
6
7#pragma once
8
9#include "rodshow.h"
10#include "AboutDialog.h"
11
12////////////////////////////////////////////////////////////
13// CFilterData
14
15class CFilterData
16{
17public:
18        CComPtr<IMoniker> m_pMoniker;
19        CStringW m_sMonikerDisplayName;
20        CComPtr<IPropertyBag> m_pPropertyBag;
21        CStringW m_sFriendlyName;
22
23        const CComPtr<IPropertyBag>& PropertyBagNeeded()
24        {
25                if(!m_pPropertyBag)
26                {
27                        _A(m_pMoniker);
28                        __C(m_pMoniker->BindToStorage(NULL, NULL, __uuidof(IPropertyBag), (VOID**) &m_pPropertyBag));
29                        _A(m_pPropertyBag);
30                }
31                return m_pPropertyBag;
32        }
33
34public:
35// CFilterData
36        CFilterData() throw()
37        {
38        }
39        CFilterData(IMoniker* pMoniker) throw() :
40                m_pMoniker(pMoniker)
41        {
42        }
43        const CComPtr<IMoniker>& GetMoniker() const throw()
44        {
45                return m_pMoniker;
46        }
47        CStringW GetMonikerDisplayName()
48        {
49                _A(m_pMoniker);
50                if(m_sMonikerDisplayName.IsEmpty())
51                        m_sMonikerDisplayName = _FilterGraphHelper::GetMonikerDisplayName(m_pMoniker);
52                return m_sMonikerDisplayName;
53        }
54        CStringW GetFriendlyName()
55        {
56                if(m_sFriendlyName.IsEmpty())
57                        m_sFriendlyName = _FilterGraphHelper::ReadPropertyBagString(PropertyBagNeeded(), L"FriendlyName");
58                return m_sFriendlyName;
59        }
60        CComPtr<IBaseFilter> CreateBaseFilterInstance() const
61        {
62                _A(m_pMoniker);
63                CComPtr<IBaseFilter> pBaseFilter;
64                __C(m_pMoniker->BindToObject(NULL, NULL, __uuidof(IBaseFilter), (VOID**) &pBaseFilter));
65                return pBaseFilter;
66        }
67};
68
69////////////////////////////////////////////////////////////
70// CFilterDataListT
71
72template <typename _FilterData, const GUID* t_pCategory>
73class CFilterDataListT :
74        public CRoListT<_FilterData>
75{
76public:
77        typedef _FilterData CFilterData;
78
79public:
80// CFilterDataListT
81        VOID Initialize()
82        {
83                RemoveAll();
84                CComPtr<ICreateDevEnum> pCreateDevEnum;
85                __C(pCreateDevEnum.CoCreateInstance(CLSID_SystemDeviceEnum));
86                CComPtr<IEnumMoniker> pEnumMoniker;
87                __C(pCreateDevEnum->CreateClassEnumerator(*t_pCategory, &pEnumMoniker, 0));
88                CComPtr<IMoniker> pMoniker;
89                while(pEnumMoniker->Next(1, &pMoniker, NULL) == S_OK)
90                {
91                        _W(AddTail(_FilterData(pMoniker)));
92                        pMoniker.Release();
93                }
94                #pragma region Duplicate Suffixes
95                CRoMapT<CStringW, CRoArrayT<_FilterData*>, CStringElementTraitsI<CStringW>> FriendlyNameMap;
96                for(POSITION Position = GetHeadPosition(); Position; GetNext(Position))
97                {
98                        _FilterData& FilterData = GetAt(Position);
99                        const CStringW sFriendlyName = FilterData.GetFriendlyName();
100                        _W(FriendlyNameMap[sFriendlyName].Add(&FilterData) >= 0);
101                }
102                for(POSITION Position = FriendlyNameMap.GetStartPosition(); Position; FriendlyNameMap.GetNext(Position))
103                {
104                        const CStringW& sFriendlyName = FriendlyNameMap.GetKeyAt(Position);
105                        CRoArrayT<_FilterData*>& Array = FriendlyNameMap.GetValueAt(Position);
106                        if(Array.GetCount() <= 1)
107                                continue;
108                        for(SIZE_T nIndex = 0; nIndex < Array.GetCount(); nIndex++)
109                                Array[nIndex]->m_sFriendlyName = AtlFormatStringT<CStringW>(L"%s #%d", sFriendlyName, nIndex + 1);
110                }
111                #pragma endregion
112        }
113        POSITION LookupMonikerDisplayName(LPCWSTR pszMonikerDisplayName)
114        {
115                _A(pszMonikerDisplayName);
116                for(POSITION Position = GetHeadPosition(); Position; GetNext(Position))
117                        if(GetAt(Position).GetMonikerDisplayName().CompareNoCase(pszMonikerDisplayName) == 0)
118                                return Position;
119                return NULL;
120        }
121        POSITION LookupMonikerDisplayName(CAtlRegExp<CAtlRECharTraitsW>& Expression)
122        {
123                CAtlREMatchContext<CAtlRECharTraitsW> MatchContext;
124                for(POSITION Position = GetHeadPosition(); Position; GetNext(Position))
125                        if(Expression.Match(GetAt(Position).GetMonikerDisplayName(), &MatchContext))
126                                return Position;
127                return NULL;
128        }
129        POSITION LookupFriendlyName(LPCWSTR pszFriendlyName)
130        {
131                _A(pszFriendlyName);
132                for(POSITION Position = GetHeadPosition(); Position; GetNext(Position))
133                        if(GetAt(Position).GetFriendlyName().Compare(pszFriendlyName) == 0)
134                                return Position;
135                return NULL;
136        }
137        POSITION LookupFriendlyName(CAtlRegExp<CAtlRECharTraitsW>& Expression)
138        {
139                CAtlREMatchContext<CAtlRECharTraitsW> MatchContext;
140                for(POSITION Position = GetHeadPosition(); Position; GetNext(Position))
141                        if(Expression.Match(GetAt(Position).GetFriendlyName(), &MatchContext))
142                                return Position;
143                return NULL;
144        }
145        POSITION LookupGenericName(LPCWSTR pszGenericName)
146        {
147                _A(pszGenericName);
148                POSITION Position;
149                Position = LookupMonikerDisplayName(pszGenericName);
150                if(Position)
151                        return Position;
152                Position = LookupFriendlyName(pszGenericName);
153                if(Position)
154                        return Position;
155                CAtlRegExp<CAtlRECharTraitsW> Expression;
156                if(Expression.Parse(pszGenericName, TRUE) == REPARSE_ERROR_OK)
157                {
158                        Position = LookupMonikerDisplayName(Expression);
159                        if(Position)
160                                return Position;
161                        Position = LookupFriendlyName(Expression);
162                        if(Position)
163                                return Position;
164                }
165                return NULL;
166        }
167};
168
169////////////////////////////////////////////////////////////
170// CAudioCaptureSourceData, CAudioCaptureSourceDataList
171
172typedef CFilterData CAudioCaptureSourceData;
173typedef CFilterDataListT<CAudioCaptureSourceData, &CLSID_AudioInputDeviceCategory> CAudioCaptureSourceDataList;
174
175////////////////////////////////////////////////////////////
176// CVideoCaptureSourceData, CVideoCaptureSourceDataList
177
178typedef CFilterData CVideoCaptureSourceData;
179typedef CFilterDataListT<CVideoCaptureSourceData, &CLSID_VideoInputDeviceCategory> CVideoCaptureSourceDataList;
180
181////////////////////////////////////////////////////////////
182// CMainDialog
183
184class CMainDialog : 
185        public CAxDialogImpl<CMainDialog>
186{
187public:
188        enum { IDD = IDD_MAIN };
189
190BEGIN_MSG_MAP_EX(CMainDialog)
191        CHAIN_MSG_MAP(CAxDialogImpl<CMainDialog>)
192        MSG_WM_INITDIALOG(OnInitDialog)
193        MSG_WM_DESTROY(OnDestroy)
194        MSG_WM_TIMER(OnTimer)
195        MSG_WM_SYSCOMMAND(OnSysCommand)
196        COMMAND_ID_HANDLER_EX(IDCANCEL, OnCommand)
197        COMMAND_HANDLER_EX(IDC_START, BN_CLICKED, OnStartClicked)
198        COMMAND_HANDLER_EX(IDC_STOP, BN_CLICKED, OnStopClicked)
199        REFLECT_NOTIFICATIONS()
200END_MSG_MAP()
201
202public:
203
204        ////////////////////////////////////////////////////////
205        // Timer Identifiers
206
207        enum 
208        {
209                TIMER_FIRST,
210                TIMER_UPDATE
211        };
212
213        ////////////////////////////////////////////////////////
214        // CRendererFilter
215
216        class ATL_NO_VTABLE CRendererFilter :
217                public CComObjectRootEx<CComMultiThreadModelNoCS>,
218                public CBaseFilterT<CRendererFilter>,
219                public CBasePersistT<CRendererFilter>,
220                public CAmFilterMiscFlagsT<CRendererFilter, AM_FILTER_MISC_FLAGS_IS_RENDERER>
221        {
222        public:
223                //enum { IDR = IDR_RENDERERFILTER };
224
225        DECLARE_NO_REGISTRY() //DECLARE_REGISTRY_RESOURCEID(IDR)
226
227        DECLARE_PROTECT_FINAL_CONSTRUCT()
228
229        //DECLARE_QI_TRACE(CRendererFilter)
230
231        BEGIN_COM_MAP(CRendererFilter)
232                COM_INTERFACE_ENTRY(IBaseFilter)
233                COM_INTERFACE_ENTRY(IMediaFilter)
234                COM_INTERFACE_ENTRY_IID(__uuidof(IPersist), IBaseFilter)
235                COM_INTERFACE_ENTRY(IAMFilterMiscFlags)
236        END_COM_MAP()
237
238                ////////////////////////////////////////////////////////
239                // CInputPin
240
241                class ATL_NO_VTABLE CInputPin :
242                        public CComObjectRootEx<CComMultiThreadModelNoCS>,
243                        public CInputPinT<CInputPin, CRendererFilter>
244                {
245                public:
246
247                //DECLARE_QI_TRACE(CRendererFilter::CInputPin)
248
249                BEGIN_COM_MAP(CInputPin)
250                        COM_INTERFACE_ENTRY(IPin)
251                        COM_INTERFACE_ENTRY(IMemInputPin)
252                END_COM_MAP()
253
254                private:
255                        GUID m_MajorType;
256
257                public:
258                // CInputPin
259                        CInputPin() throw() :
260                                m_MajorType(MEDIATYPE_NULL)
261                        {
262                                _Z4(atlTraceRefcount, 4, _T("this 0x%p\n"), this);
263                        }
264                        ~CInputPin() throw()
265                        {
266                                _Z4(atlTraceRefcount, 4, _T("this 0x%p\n"), this);
267                        }
268                        VOID EnumerateMediaTypes(CAtlList<CMediaType>& MediaTypeList) const
269                        {
270                                CRoCriticalSectionLock DataLock(GetDataCriticalSection());
271                                _A(m_MajorType != MEDIATYPE_NULL);
272                                AM_MEDIA_TYPE MediaType;
273                                ZeroMemory(&MediaType, sizeof MediaType);
274                                MediaType.majortype = m_MajorType;
275                                _W(MediaTypeList.AddTail(&MediaType));
276                        }
277                        BOOL CheckMediaType(const CMediaType& pMediaType) const throw()
278                        {
279                                _A(pMediaType);
280                                CRoCriticalSectionLock DataLock(GetDataCriticalSection());
281                                if(GetMediaTypeReference())
282                                        return GetMediaTypeReference().Compare(pMediaType);
283                                return pMediaType->majortype == m_MajorType;
284                        }
285                        VOID SetMajorType(const GUID& MajorType) throw()
286                        {
287                                CRoCriticalSectionLock DataLock(GetDataCriticalSection());
288                                _A(!GetMediaTypeReference());
289                                m_MajorType = MajorType;
290                        }
291                };
292
293        private:
294                CObjectPtr<CInputPin> m_pInputPin;
295                SIZE_T m_nMediaSampleCount;
296                REFERENCE_TIME m_nLastMediaSampleTime;
297
298        public:
299        // CRendererFilter
300                CRendererFilter() throw() :
301                        CBasePersistT<CRendererFilter>(GetDataCriticalSection())
302                {
303                        _Z4(atlTraceRefcount, 4, _T("this 0x%p\n"), this);
304                }
305                ~CRendererFilter() throw()
306                {
307                        _Z4(atlTraceRefcount, 4, _T("this 0x%p\n"), this);
308                }
309                HRESULT FinalConstruct() throw()
310                {
311                        _ATLTRY
312                        {
313                                m_pInputPin.Construct()->Initialize(this, L"Input");
314                                AddPin(m_pInputPin);
315                        }
316                        _ATLCATCH(Exception)
317                        {
318                                _C(Exception);
319                        }
320                        return S_OK;
321                }
322                VOID FinalRelease()
323                {
324                        m_pInputPin = NULL;
325                }
326                VOID CueFilter()
327                {
328                        CRoCriticalSectionLock DataLock(GetDataCriticalSection());
329                        m_nMediaSampleCount = 0;
330                        m_nLastMediaSampleTime = 0;
331                }
332                VOID ReceiveMediaSample(IPin* pPin, IMediaSample2* pMediaSample, HRESULT& nReceiveResult)
333                {
334                        _A(pPin && pMediaSample); 
335                        _A(nReceiveResult == S_OK);
336                        CMediaSampleProperties Properties(pMediaSample);
337                        CRoCriticalSectionLock DataLock(GetDataCriticalSection());
338                        m_nMediaSampleCount++;
339                        if(Properties.dwSampleFlags & AM_SAMPLE_TIMEVALID)
340                                m_nLastMediaSampleTime = Properties.tStart;
341                }
342                const CObjectPtr<CInputPin>& GetInputPin() const throw()
343                {
344                        return m_pInputPin;
345                }
346                VOID Initialize(const GUID& MajorType)
347                {
348                        GetInputPin()->SetMajorType(MajorType);
349                }
350                VOID GetData(SIZE_T& nMediaSampleCount, REFERENCE_TIME& nLastMediaSampleTime) const throw()
351                {
352                        CRoCriticalSectionLock DataLock(GetDataCriticalSection());
353                        nMediaSampleCount = m_nMediaSampleCount;
354                        nLastMediaSampleTime = m_nLastMediaSampleTime;
355                }
356        };
357
358private:
359        CRoComboBoxT<CFilterData, CRoListControlDataTraitsT> m_VideoDeviceComboBox;
360        CRoEdit m_VideoTimeEdit;
361        CRoComboBoxT<CFilterData, CRoListControlDataTraitsT> m_AudioDeviceComboBox;
362        CRoEdit m_AudioTimeEdit;
363        CRoEdit m_SystemTimeEdit;
364        CButton m_StartButton;
365        CButton m_StopButton;
366        CGenericFilterGraph m_FilterGraph;
367        CObjectPtr<CRendererFilter> m_pVideoRendererFilter;
368        CObjectPtr<CRendererFilter> m_pAudioRendererFilter;
369        CComPtr<IReferenceClock> m_pReferenceClock;
370        REFERENCE_TIME m_nAnchorTime;
371        CString m_sLog;
372        UINT m_nTimerEventIndex;
373
374public:
375// CMainDialog
376        CMainDialog()
377        {
378        }
379        VOID ReleaseFilterGraph()
380        {
381                if(m_FilterGraph.m_pMediaControl)
382                        _V(m_FilterGraph.m_pMediaControl->Stop());
383                m_FilterGraph.Release();
384                m_pVideoRendererFilter.Release();
385                m_pAudioRendererFilter.Release();
386                m_pReferenceClock.Release();
387        }
388        static CComPtr<IPin> GetCapturePin(IBaseFilter* pBaseFilter)
389        {
390                _A(pBaseFilter);
391                _FilterGraphHelper::CPinArray PinArray;
392                _FilterGraphHelper::GetFilterPins(pBaseFilter, PINDIR_OUTPUT, PinArray);
393                CComPtr<IPin> pCapturePin, pAssumedCapturePin;
394                for(SIZE_T nIndex = 0; nIndex < PinArray.GetCount(); nIndex++)
395                {
396                        const CComPtr<IPin>& pPin = PinArray[nIndex];
397                        if(!pAssumedCapturePin)
398                        {
399                                pAssumedCapturePin = pPin;
400                                // SUGG: Check Media Type
401                        }
402                        const CComQIPtr<IKsPropertySet> pKsPropertySet = pPin;
403                        if(pKsPropertySet)
404                        {
405                                GUID PinCategory = GUID_NULL;
406                                DWORD nPinCategorySize = 0;
407                                const HRESULT nGetResult = pKsPropertySet->Get(AMPROPSETID_Pin, AMPROPERTY_PIN_CATEGORY, NULL, 0, &PinCategory, sizeof PinCategory, &nPinCategorySize);
408                                _Z4(atlTraceGeneral, 4, _T("nGetResult 0x%08x, nPinCategorySize %d, PinCategory %ls\n"), nGetResult, nPinCategorySize, _PersistHelper::StringFromIdentifier(PinCategory));
409                                if(SUCCEEDED(nGetResult))
410                                        if(nPinCategorySize == sizeof PinCategory && PinCategory == PIN_CATEGORY_CAPTURE)
411                                        {
412                                                pCapturePin = pPin;
413                                                break;
414                                        }
415                        }
416                }
417                return pCapturePin ? pCapturePin : pAssumedCapturePin;
418        }
419        VOID UpdateControls()
420        {
421                m_VideoDeviceComboBox.EnableWindow(m_FilterGraph.m_pFilterGraph == NULL);
422                m_VideoDeviceComboBox.GetWindow(GW_HWNDPREV).EnableWindow(m_VideoDeviceComboBox.IsWindowEnabled());
423                m_AudioDeviceComboBox.EnableWindow(m_FilterGraph.m_pFilterGraph == NULL);
424                m_AudioDeviceComboBox.GetWindow(GW_HWNDPREV).EnableWindow(m_AudioDeviceComboBox.IsWindowEnabled());
425                m_StartButton.EnableWindow(m_FilterGraph.m_pFilterGraph == NULL);
426                m_StopButton.EnableWindow(m_FilterGraph.m_pFilterGraph != NULL);
427        }
428
429// Window Message Handelrs
430        LRESULT OnInitDialog(HWND, LPARAM)
431        {
432                SetIcon(AtlLoadIconImage(IDI_MODULE, LR_DEFAULTCOLOR, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON)), TRUE);
433                SetIcon(AtlLoadIconImage(IDI_MODULE, LR_DEFAULTCOLOR, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON)), FALSE);
434                CMenuHandle Menu = GetSystemMenu(FALSE);
435                _W(Menu.AppendMenu(MF_SEPARATOR));
436                _W(Menu.AppendMenu(MF_STRING, ID_APP_ABOUT, _T("&About...")));
437                m_VideoDeviceComboBox = GetDlgItem(IDC_VIDEO_DEVICE);
438                CVideoCaptureSourceDataList VideoCaptureSourceDataList;
439                VideoCaptureSourceDataList.Initialize();
440                for(POSITION Position = VideoCaptureSourceDataList.GetHeadPosition(); Position; VideoCaptureSourceDataList.GetNext(Position))
441                {
442                        CFilterData& FilterData = VideoCaptureSourceDataList.GetAt(Position);
443                        m_VideoDeviceComboBox.AddString(CW2CT(FilterData.GetFriendlyName()), FilterData);
444                }
445                m_VideoDeviceComboBox.SetCurSel(0);
446                m_VideoTimeEdit = GetDlgItem(IDC_VIDEO_TIME);
447                m_AudioDeviceComboBox = GetDlgItem(IDC_AUDIO_DEVICE);
448                CAudioCaptureSourceDataList AudioCaptureSourceDataList;
449                AudioCaptureSourceDataList.Initialize();
450                for(POSITION Position = AudioCaptureSourceDataList.GetHeadPosition(); Position; AudioCaptureSourceDataList.GetNext(Position))
451                {
452                        CFilterData& FilterData = AudioCaptureSourceDataList.GetAt(Position);
453                        m_AudioDeviceComboBox.AddString(CW2CT(FilterData.GetFriendlyName()), FilterData);
454                }
455                m_AudioDeviceComboBox.SetCurSel(0);
456                m_AudioTimeEdit = GetDlgItem(IDC_AUDIO_TIME);
457                m_SystemTimeEdit = GetDlgItem(IDC_SYSTEM_TIME);
458                m_StartButton = GetDlgItem(IDC_START);
459                m_StopButton = GetDlgItem(IDC_STOP);
460                m_StopButton.EnableWindow(FALSE);
461                _W(CenterWindow());
462                UpdateControls();
463                #if _DEVELOPMENT
464                // TODO: ...
465                #endif // _DEVELOPMENT
466                return TRUE;
467        }
468        LRESULT OnDestroy() throw()
469        {
470                CWaitCursor WaitCursor;
471                ReleaseFilterGraph();
472                return 0;
473        }
474        LRESULT OnTimer(UINT_PTR nEvent)
475        {
476                switch(nEvent)
477                {
478                case TIMER_UPDATE:
479                        {
480                                // NOTE: A log item every half a minute
481                                const BOOL bLog = ++m_nTimerEventIndex % 30 == 0;
482                                CRoArrayT<CString> Array;
483                                REFERENCE_TIME nSystemTime;
484                                if(m_pReferenceClock)
485                                {
486                                        _V(m_pReferenceClock->GetTime(&nSystemTime));
487                                        nSystemTime -= m_nAnchorTime;
488                                        m_SystemTimeEdit.SetValue(AtlFormatString(_T("%s"), _FilterGraphHelper::FormatReferenceTime(nSystemTime)));
489                                        if(bLog)
490                                                Array.Add(AtlFormatString(_T("%I64d"), (nSystemTime + 5000i64 - 1) / 10000i64));
491                                }
492                                if(m_pVideoRendererFilter)
493                                {
494                                        SIZE_T nCount;
495                                        REFERENCE_TIME nTime;
496                                        m_pVideoRendererFilter->GetData(nCount, nTime);
497                                        m_VideoTimeEdit.SetValue(AtlFormatString(_T("%s (%s samples)"), _FilterGraphHelper::FormatReferenceTime(nTime), _StringHelper::FormatNumber((INT) nCount)));
498                                        if(bLog)
499                                        {
500                                                Array.Add(AtlFormatString(_T("%d"), nCount));
501                                                Array.Add(AtlFormatString(_T("%I64d"), (nTime + 5000i64 - 1) / 10000i64));
502                                                Array.Add(AtlFormatString(_T("%I64d"), ((nTime - nSystemTime) + 5000i64 - 1) / 10000i64));
503                                        }
504                                }
505                                if(m_pAudioRendererFilter)
506                                {
507                                        SIZE_T nCount;
508                                        REFERENCE_TIME nTime;
509                                        m_pAudioRendererFilter->GetData(nCount, nTime);
510                                        m_AudioTimeEdit.SetValue(AtlFormatString(_T("%s (%s samples)"), _FilterGraphHelper::FormatReferenceTime(nTime), _StringHelper::FormatNumber((INT) nCount)));
511                                        if(bLog)
512                                        {
513                                                Array.Add(AtlFormatString(_T("%d"), nCount));
514                                                Array.Add(AtlFormatString(_T("%I64d"), (nTime + 5000i64 - 1) / 10000i64));
515                                                Array.Add(AtlFormatString(_T("%I64d"), ((nTime - nSystemTime) + 5000i64 - 1) / 10000i64));
516                                        }
517                                }
518                                if(bLog && Array.GetCount() == 1 + 3 + 3)
519                                {
520                                        if(m_sLog.IsEmpty())
521                                        {
522                                                static LPCTSTR g_ppszHeader[] = 
523                                                {
524                                                        _T("System Time"),
525                                                        _T("Video Sample Count"),
526                                                        _T("Video Sample Time"),
527                                                        _T("Relative Video Sample Time"),
528                                                        _T("Audio Sample Count"),
529                                                        _T("Audio Sample Time"),
530                                                        _T("Relative Audio Sample Time"),
531                                                };
532                                                m_sLog.Append(_StringHelper::Join(g_ppszHeader, _T("\t")) + _T("\r\n"));
533                                        }
534                                        m_sLog.Append(_StringHelper::Join(Array, _T("\t")) + _T("\r\n"));
535                                }
536                        }
537                        break;
538                default:
539                        SetMsgHandled(FALSE);
540                }
541                return 0;
542        }
543        LRESULT OnSysCommand(UINT nCommand, CPoint)
544        {
545                switch(nCommand)
546                {
547                case ID_APP_ABOUT:
548                        {
549                                CAboutDialog Dialog;
550                                Dialog.DoModal(m_hWnd);
551                        }
552                        break;
553                default:
554                        SetMsgHandled(FALSE);
555                }
556                return 0;
557        }
558        LRESULT OnCommand(UINT, INT nIdentifier, HWND)
559        {
560                _W(EndDialog(nIdentifier));
561                return 0;
562        }
563        LRESULT OnStartClicked(UINT, INT, HWND)
564        {
565                CWaitCursor WaitCursor;
566                m_StartButton.EnableWindow(FALSE);
567                _ATLTRY
568                {
569                        ReleaseFilterGraph();
570                        m_FilterGraph.CoCreateInstance();
571                        m_FilterGraph.SetShowDestructorMessageBox(TRUE);
572                        // SUGG: Video/Audio Only Capture?
573                        _A(m_VideoDeviceComboBox.GetCurSel() >= 0 && m_AudioDeviceComboBox.GetCurSel() >= 0);
574                        #pragma region Video
575                        {
576                                CFilterData& VideoFilterData = m_VideoDeviceComboBox.GetItemData(m_VideoDeviceComboBox.GetCurSel());
577                                const CComPtr<IBaseFilter> pSourceBaseFilter = VideoFilterData.CreateBaseFilterInstance();
578                                __C(m_FilterGraph->AddFilter(pSourceBaseFilter, CT2CW(_T("Video Source"))));
579                                CObjectPtr<CRendererFilter> pRendererFilter;
580                                pRendererFilter.Construct();
581                                pRendererFilter->Initialize(MEDIATYPE_Video);
582                                __C(m_FilterGraph->AddFilter(pRendererFilter, CT2CW(_T("Video Renderer"))));
583                                __C(m_FilterGraph->Connect(GetCapturePin(pSourceBaseFilter), pRendererFilter->GetInputPin()));
584                                m_pVideoRendererFilter = pRendererFilter;
585                        }
586                        #pragma endregion
587                        #pragma region Audio
588                        {
589                                CFilterData& AudioFilterData = m_AudioDeviceComboBox.GetItemData(m_AudioDeviceComboBox.GetCurSel());
590                                const CComPtr<IBaseFilter> pSourceBaseFilter = AudioFilterData.CreateBaseFilterInstance();
591                                __C(m_FilterGraph->AddFilter(pSourceBaseFilter, CT2CW(_T("Audio Source"))));
592                                CObjectPtr<CRendererFilter> pRendererFilter;
593                                pRendererFilter.Construct();
594                                pRendererFilter->Initialize(MEDIATYPE_Audio);
595                                __C(m_FilterGraph->AddFilter(pRendererFilter, CT2CW(_T("Audio Renderer"))));
596                                const CComPtr<IPin> pCapturePin = GetCapturePin(pSourceBaseFilter);
597                                _ATLTRY
598                                {
599                                        const CComQIPtr<IAMBufferNegotiation> pAmBufferNegotiation = pCapturePin;
600                                        __D(pAmBufferNegotiation, E_NOINTERFACE);
601                                        const CComQIPtr<IAMStreamConfig> pAmStreamConfig = pCapturePin;
602                                        __D(pAmStreamConfig, E_NOINTERFACE);
603                                        CMediaType pMediaType;
604                                        __C(pAmStreamConfig->GetFormat(&pMediaType));
605                                        const CWaveFormatEx* pWaveFormatEx = pMediaType.GetWaveFormatEx();
606                                        __D(pWaveFormatEx, E_UNNAMED);
607                                        ALLOCATOR_PROPERTIES Properties;
608                                        Properties.cbAlign = -1;
609                                        Properties.cbBuffer = pWaveFormatEx->nAvgBytesPerSec / 10; // 100 millisecond
610                                        Properties.cbPrefix = -1;
611                                        Properties.cBuffers = 50; // 50 buffers (5 seconds in total)
612                                        __C(pAmBufferNegotiation->SuggestAllocatorProperties(&Properties));
613                                }
614                                _ATLCATCHALL()
615                                {
616                                        _Z_EXCEPTION();
617                                }
618                                __C(m_FilterGraph->Connect(pCapturePin, pRendererFilter->GetInputPin()));
619                                m_pAudioRendererFilter = pRendererFilter;
620                        }
621                        #pragma endregion
622                        m_FilterGraph.SetShowDestructorMessageBox(FALSE);
623                        __C(m_pReferenceClock.CoCreateInstance(CLSID_SystemClock));
624                        __C(m_pReferenceClock->GetTime(&m_nAnchorTime));
625                        __C(m_FilterGraph.m_pMediaControl->Run());
626                        m_sLog.Empty();
627                        m_nTimerEventIndex = 0;
628                        SetTimer(TIMER_UPDATE, 1000);
629                }
630                _ATLCATCHALL()
631                {
632                        ReleaseFilterGraph();
633                        UpdateControls();
634                        _ATLRETHROW;
635                }
636                UpdateControls();
637                return 0;
638        }
639        LRESULT OnStopClicked(UINT, INT, HWND)
640        {
641                CWaitCursor WaitCursor;
642                m_StopButton.EnableWindow(FALSE);
643                _ATLTRY
644                {
645                        KillTimer(TIMER_UPDATE);
646                        ReleaseFilterGraph();
647                }
648                _ATLCATCHALL()
649                {
650                        UpdateControls();
651                        _ATLRETHROW;
652                }
653                UpdateControls();
654                if(!m_sLog.IsEmpty())
655                {
656                        CString sLog;
657                        OSVERSIONINFO VersionInformation = { sizeof VersionInformation };
658                        _W(GetVersionEx(&VersionInformation));
659                        _A(VersionInformation.dwPlatformId == VER_PLATFORM_WIN32_NT);
660                        sLog += AtlFormatString(_T("Windows Version") _T("\t") _T("%d.%d.%d %s") _T("\r\n"), VersionInformation.dwMajorVersion, VersionInformation.dwMinorVersion, VersionInformation.dwBuildNumber, VersionInformation.szCSDVersion);
661                        CFilterData& VideoFilterData = m_VideoDeviceComboBox.GetItemData(m_VideoDeviceComboBox.GetCurSel());
662                        sLog += AtlFormatString(_T("Video Device") _T("\t") _T("%ls") _T("\t") _T("%ls") _T("\r\n"), VideoFilterData.GetFriendlyName(), VideoFilterData.GetMonikerDisplayName());
663                        CFilterData& AudioFilterData = m_AudioDeviceComboBox.GetItemData(m_AudioDeviceComboBox.GetCurSel());
664                        sLog += AtlFormatString(_T("Audio Device") _T("\t") _T("%ls") _T("\t") _T("%ls") _T("\r\n"), AudioFilterData.GetFriendlyName(), AudioFilterData.GetMonikerDisplayName());
665                        sLog += _T("\r\n");
666                        sLog += m_sLog;
667                        SetClipboardText(m_hWnd, sLog);
668                        MessageBeep(MB_OK);
669                }
670                return 0;
671        }
672};
Note: See TracBrowser for help on using the repository browser.