source: trunk/DirectShowSpy/MediaSampleTrace.h @ 440

Last change on this file since 440 was 440, checked in by roman, 7 years ago

Added media sample trace API and UI

File size: 35.4 KB
Line 
1////////////////////////////////////////////////////////////
2// Copyright (C) Roman Ryltsov, 2008-2015
3// Created by Roman Ryltsov roman@alax.info, http://alax.info
4//
5// This source code is published to complement DirectShowSpy developer powertoy
6// and demonstrate the internal use of APIs and tricks powering the tool. It is
7// allowed to freely re-use the portions of the code in other projects, commercial
8// or otherwise (provided that you don’t pretend that you wrote the original tool).
9//
10// Please keep in mind that DirectShowSpy is a developer tool, it is strongly recommended
11// that it is not shipped with release grade software. It is allowed to distribute
12// DirectShowSpy if only it is not registered with Windows by default and either
13// used privately, or registered on specific throubleshooting request. The advice applies
14// to hooking methods used by DirectShowSpy in general as well.
15
16#pragma once
17
18#include "rodshow.h"
19#include "Module_i.h"
20#include "Common.h"
21#include "FilterGraphHelper.h"
22
23////////////////////////////////////////////////////////////
24// CMediaSampleTraceBase
25
26class CMediaSampleTraceBase
27{
28public:
29
30        ////////////////////////////////////////////////////////
31        // Structure
32
33        #pragma pack(push, 1)
34
35        enum
36        {
37                HEADERFLAGS_NONE = 0,
38        };
39
40        typedef struct _HEADER
41        {
42                UINT32 nCapacity;
43                UINT32 nFlags;
44                UINT32 nVersion;
45                UINT32 nItemCount;
46        } HEADER;
47
48        enum
49        {
50                ITEMFLAGS_NONE = 0,
51                ITEMFLAG_INVALID = 1,
52        };
53
54        typedef struct _ITEM
55        {
56                UINT32 nFlags;
57                UINT32 nProcessIdentifier;
58                UINT32 nPageIdentifier;
59                UINT64 nFilterGraphIdentifier;
60                WCHAR pszFilterGraphName[128];
61        } ITEM;
62
63        enum
64        {
65                PAGEHEADERFLAGS_NONE = 0,
66                PAGEHEADERFLAG_X64 = 1,
67        };
68
69        typedef struct _PAGEHEADER
70        {
71                UINT32 nCapacity;
72                UINT32 nFlags;
73                UINT32 nProcessIdentifier;
74                UINT32 nItemCount;
75        } PAGEHEADER;
76
77        enum
78        {
79                PAGEITEMFLAGS_NONE = 0,
80                PAGEITEMFLAG_NEWSEGMENT = 0,
81                PAGEITEMFLAG_MEDIASAMPLE = 1,
82                PAGEITEMFLAG_ENDOFSTREAM = 2,
83                PAGEITEMFLAG_COMMENT = 3,
84                PAGEITEMFLAG_TYPE_MASK = 0x03,
85        };
86
87        typedef struct _PAGEITEM
88        {
89                UINT32 nFlags;
90                UINT32 nThreadIdentifier;
91                UINT64 nFilterIdentifier;
92                WCHAR pszFilterName[32];
93                WCHAR pszStreamName[32];
94                UINT64 nTime;
95                union
96                {
97                        struct
98                        {
99                                REFERENCE_TIME nStartTime;
100                                REFERENCE_TIME nStopTime;
101                                DOUBLE fRate;
102                        } NewSegment;
103                        struct
104                        {
105                                AM_SAMPLE2_PROPERTIES Properties;
106                        } MediaSample;
107                } Data;
108                WCHAR pszComment[64];
109        } PAGEITEM;
110
111        #pragma pack(pop)
112
113        ////////////////////////////////////////////////////////
114        // CData
115
116        class CData
117        {
118        public:
119
120                ///////////////////////////////////////////////////////
121                // CItem
122
123                class CItem
124                {
125                public:
126                        ITEM m_Item;
127                        PAGEITEM m_PageItem;
128
129                public:
130                // CItem
131                        LPCTSTR FormatType() const
132                        {
133                                switch(m_PageItem.nFlags & PAGEITEMFLAG_TYPE_MASK)
134                                {
135                                case PAGEITEMFLAG_NEWSEGMENT:
136                                        return _T("New Segment");
137                                case PAGEITEMFLAG_MEDIASAMPLE:
138                                        return _T("Media Sample");
139                                case PAGEITEMFLAG_ENDOFSTREAM:
140                                        return _T("End of Stream");
141                                //case PAGEITEMFLAG_COMMENT:
142                                //      return _T("Comment");
143                                }
144                                return _T("Comment");
145                        }
146                };
147
148                ////////////////////////////////////////////////////
149                // CItemSortTraits
150
151                class CItemSortTraits :
152                        public CDefaultSortTraitsT<CItem>
153                {
154                public:
155                // CItemSortTraits
156                        static INT_PTR CompareElements(const CItem& Item1, const CItem& Item2, PARAMETERARGUMENT)
157                        {
158                                const INT64 nTime = Item1.m_PageItem.nTime - Item2.m_PageItem.nTime;
159                                return (nTime < 0) ? -1 : (nTime > 0) ? 1 : 0;
160                        }
161                };
162
163        public:
164                CRoArrayT<CItem> m_ItemArray;
165
166        public:
167        // CData
168                VOID Initialize()
169                {
170                        m_ItemArray.SetCount(0, 32768);
171                }
172                VOID Add(const HEADER* pHeader, const ITEM* pItem, const PAGEHEADER* pPageHeader, const PAGEITEM* pPageItem)
173                {
174                        _A(pHeader && pItem && pPageHeader && pPageItem);
175                        pHeader; pPageHeader;
176                        const SIZE_T nIndex = m_ItemArray.Add();
177                        CItem& Item = m_ItemArray[nIndex];
178                        Item.m_Item = *pItem;
179                        Item.m_PageItem = *pPageItem;
180                }
181                VOID Sort()
182                {
183                        _SortHelper::QuickSort<CItemSortTraits>(m_ItemArray);
184                }
185        };
186
187        ////////////////////////////////////////////////////////
188        // CPages
189
190        class CPages
191        {
192        private:
193                UINT64 m_nFilterGraphIdentifier;
194                CStringW m_sFilterGraphName;
195                CMutex m_Mutex;
196                CAtlFileMapping<HEADER> m_FileMapping;
197
198        public:
199        // CPages
200                static LPCTSTR GetMutexName()
201                {
202                        return _T("DirectShowSpy.MediaSamplePageRegistry.Access");
203                }
204                static SIZE_T GetFileMappingCapacity()
205                {
206                        return 1 << 20; // 1 MB
207                }
208                static LPCTSTR GetFileMappingName()
209                {
210                        return _T("DirectShowSpy.MediaSamplePageRegistry");
211                }
212                static CString GetPageMutexName(UINT32 nProcessIdentifier, UINT64 nPageIdentifier)
213                {
214                        return AtlFormatString(_T("DirectShowSpy.MediaSamplePage.%08X.%08X.Access"), nProcessIdentifier, nPageIdentifier);
215                }
216                static SIZE_T GetPageFileMappingCapacity()
217                {
218                        return 4 << 20; // 4 MB
219                }
220                static CString GetPageFileMappingName(UINT32 nProcessIdentifier, UINT64 nPageIdentifier)
221                {
222                        return AtlFormatString(_T("DirectShowSpy.MediaSamplePage.%08X.%08X"), nProcessIdentifier, nPageIdentifier);
223                }
224                BOOL Initialize(BOOL bCreate = FALSE)
225                {
226                        _A(!m_Mutex && !m_FileMapping);
227                        if(!bCreate)
228                        {
229                                if(!m_Mutex.Open(MUTEX_ALL_ACCESS, FALSE, GetMutexName()))
230                                        return FALSE;
231                                _ATLTRY
232                                {
233                                        //CMutexLock MutexLock(m_Mutex);
234                                        __C(m_FileMapping.OpenMapping(GetFileMappingName(), GetFileMappingCapacity()));
235                                }
236                                _ATLCATCHALL()
237                                {
238                                        m_Mutex.Close();
239                                        _ATLRETHROW;
240                                }
241                        } else
242                        {
243                                __E(m_Mutex.Create(NULL, FALSE, GetMutexName()));
244                                //CMutexLock MutexLock(m_Mutex);
245                                __C(m_FileMapping.MapSharedMem(GetFileMappingCapacity(), GetFileMappingName()));
246                        }
247                        return TRUE;
248                }
249                VOID GetData(CData& Data)
250                {
251                        _A(m_Mutex && m_FileMapping);
252                        Data.Initialize();
253                        CMutexLock MutexLock(m_Mutex);
254                        HEADER* pHeader = m_FileMapping;
255                        _A(pHeader->nCapacity);
256                        for(UINT32 nItemIndex = 0; nItemIndex < pHeader->nItemCount; nItemIndex++)
257                        {
258                                ITEM* pItem = (ITEM*) (pHeader + 1) + nItemIndex;
259                                if(pItem->nFlags & ITEMFLAG_INVALID)
260                                        continue;
261                                _ATLTRY
262                                {
263                                        CMutex PageMutex;
264                                        __E(PageMutex.Open(MUTEX_ALL_ACCESS, FALSE, GetPageMutexName(pItem->nProcessIdentifier, pItem->nPageIdentifier)));
265                                        CAtlFileMapping<PAGEHEADER> PageFileMapping;
266                                        __C(PageFileMapping.OpenMapping(GetPageFileMappingName(pItem->nProcessIdentifier, pItem->nPageIdentifier), GetPageFileMappingCapacity()));
267                                        PAGEHEADER* pPageHeader = PageFileMapping;
268                                        CMutexLock MutexLock(PageMutex);
269                                        #pragma region Bitness
270                                        // SUGG: Support non-native bitness through conversion
271                                        #if defined(_WIN64)
272                                                if(!(pPageHeader->nFlags & PAGEHEADERFLAG_X64))
273                                                        continue;
274                                        #else
275                                                if(pPageHeader->nFlags & PAGEHEADERFLAG_X64)
276                                                        continue;
277                                        #endif // defined(_WIN64)
278                                        #pragma endregion
279                                        for(UINT32 nItemIndex = 0; nItemIndex < pPageHeader->nItemCount; nItemIndex++)
280                                        {
281                                                PAGEITEM* pPageItem = (PAGEITEM*) (pPageHeader + 1) + nItemIndex;
282                                                Data.Add(pHeader, pItem, pPageHeader, pPageItem);
283                                        }
284                                        continue;
285                                }
286                                _ATLCATCHALL()
287                                {
288                                        _Z_EXCEPTION();
289                                }
290                                pItem->nFlags |= ITEMFLAG_INVALID;
291                        }
292                }
293                VOID ResetData()
294                {
295                        CMutexLock MutexLock(m_Mutex);
296                        HEADER* pHeader = m_FileMapping;
297                        _A(pHeader->nCapacity);
298                        pHeader->nItemCount = 0;
299                        pHeader->nVersion++;
300                }
301                VOID Initialize(UINT64 nFilterGraphIdentifier, const CStringW& sFilterGraphName)
302                {
303                        _A(!m_Mutex && !m_FileMapping);
304                        m_nFilterGraphIdentifier = nFilterGraphIdentifier;
305                        m_sFilterGraphName = sFilterGraphName;
306                        __E(m_Mutex.Create(NULL, FALSE, GetMutexName()));
307                        CMutexLock MutexLock(m_Mutex);
308                        BOOL bOpen = FALSE;
309                        __C(m_FileMapping.MapSharedMem(GetFileMappingCapacity(), GetFileMappingName(), &bOpen));
310                        HEADER* pHeader = m_FileMapping;
311                        if(!pHeader->nCapacity)
312                        {
313                                _A(!bOpen);
314                                pHeader->nCapacity = (UINT32) GetFileMappingCapacity();
315                                pHeader->nFlags = HEADERFLAGS_NONE;
316                                pHeader->nVersion = 0;
317                                pHeader->nItemCount = 0;
318                        } else
319                                _A(bOpen);
320                        #if defined(_DEBUG)
321                                _Z4(atlTraceGeneral, 4, _T("File mapping size %d, item size %d, item capacity %d\n"), GetFileMappingCapacity(), sizeof (ITEM), (GetFileMappingCapacity() - sizeof (HEADER)) / sizeof (ITEM));
322                                _Z4(atlTraceGeneral, 4, _T("Page file mapping size %d, page item size %d, page item capacity %d\n"), GetPageFileMappingCapacity(), sizeof (PAGEITEM), (GetPageFileMappingCapacity() - sizeof (PAGEHEADER)) / sizeof (PAGEITEM));
323                        #endif // defined(_DEBUG)
324                }
325                VOID CreatePage(UINT32& nPageIdentifier, CMutex& Mutex, CAtlFileMapping<PAGEHEADER>& FileMapping)
326                {
327                        _A(!Mutex && !FileMapping);
328                        // SUGG: Random identifiers
329                        for(nPageIdentifier = 0; ; nPageIdentifier++)
330                        {
331                                if(!Mutex.Create(NULL, FALSE, GetPageMutexName(GetCurrentProcessId(), nPageIdentifier)))
332                                {
333                                        const HRESULT nCreateResult = AtlHresultFromLastError();
334                                        __D(nCreateResult == E_ACCESSDENIED, nCreateResult);
335                                        continue; // Already Exists, Access Denied
336                                }
337                                _ATLTRY
338                                {
339                                        CMutexLock MutexLock(Mutex);
340                                        if(GetLastError() != ERROR_ALREADY_EXISTS)
341                                        {
342                                                BOOL bOpen = FALSE;
343                                                __C(FileMapping.MapSharedMem(GetPageFileMappingCapacity(), GetPageFileMappingName(GetCurrentProcessId(), nPageIdentifier), &bOpen));
344                                                _ATLTRY
345                                                {
346                                                        __D(!bOpen, E_UNNAMED);
347                                                        PAGEHEADER* pPageHeader = FileMapping;
348                                                        _A(!pPageHeader->nCapacity);
349                                                        pPageHeader->nCapacity = (UINT32) GetPageFileMappingCapacity();
350                                                        pPageHeader->nFlags = 0;
351                                                        #if defined(_WIN64)
352                                                                pPageHeader->nFlags |= PAGEHEADERFLAG_X64;
353                                                        #endif // defined(_WIN64)
354                                                        pPageHeader->nProcessIdentifier = (UINT32) GetCurrentProcessId();
355                                                        pPageHeader->nItemCount = 0;
356                                                        MutexLock.Unlock();
357                                                        #pragma region Link Page
358                                                        {
359                                                                CMutexLock MutexLock(m_Mutex);
360                                                                HEADER* pHeader = m_FileMapping;
361                                                                const SIZE_T nCapacity = sizeof *pHeader + (pHeader->nItemCount + 1) * sizeof (ITEM);
362                                                                __D(nCapacity <= (SIZE_T) pHeader->nCapacity, HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW));
363                                                                ITEM* pItem = (ITEM*) (pHeader + 1) + pHeader->nItemCount;
364                                                                pItem->nFlags = ITEMFLAGS_NONE;
365                                                                pItem->nProcessIdentifier = (UINT32) GetCurrentProcessId();
366                                                                pItem->nPageIdentifier = nPageIdentifier;
367                                                                pItem->nFilterGraphIdentifier = m_nFilterGraphIdentifier;
368                                                                wcsncpy_s(pItem->pszFilterGraphName, m_sFilterGraphName, _TRUNCATE);
369                                                                pHeader->nItemCount++;
370                                                                pHeader->nVersion++;
371                                                        }
372                                                        #pragma endregion
373                                                        break;
374                                                }
375                                                _ATLCATCHALL()
376                                                {
377                                                        _V(FileMapping.Unmap());
378                                                        _ATLRETHROW;
379                                                }
380                                        }
381                                }
382                                _ATLCATCHALL()
383                                {
384                                        _Z_EXCEPTION();
385                                }
386                                Mutex.Close();
387                        }
388                }
389        };
390
391        ////////////////////////////////////////////////////////
392        // CPage
393
394        class CPage
395        {
396        public:
397
398                ///////////////////////////////////////////////////
399                // CItem
400
401                class CItem
402                {
403                public:
404                        UINT32 m_nPageIdentifier;
405                        CMutex m_Mutex;
406                        CAtlFileMapping<PAGEHEADER> m_FileMapping;
407                        BOOL m_bActive;
408
409                public:
410                // CItem
411                };
412
413        private:
414                CRoListT<CItem> m_ItemList;
415
416        public:
417        // CPage
418                VOID Register(CPages& Pages, UINT64 nFilterIdentifier, const CStringW& sFilterName, LPCWSTR pszStreamName, const PAGEITEM& PageItem, LPCWSTR pszComment)
419                {
420                        const UINT64 nTime = (UINT64) CUsAccurateFileTime::GetTime();
421                        for(UINT nIteration = 0; ; nIteration++)
422                        {
423                                _A(nIteration < 2);
424                                if(!m_ItemList.IsEmpty() && m_ItemList.GetTail().m_bActive)
425                                {
426                                        CMutexLock MutexLock(m_ItemList.GetTail().m_Mutex);
427                                        PAGEHEADER* pPageHeader = m_ItemList.GetTail().m_FileMapping;
428                                        const SIZE_T nCapacity = sizeof *pPageHeader + (pPageHeader->nItemCount + 1) * sizeof (PAGEITEM);
429                                        if(nCapacity <= (SIZE_T) pPageHeader->nCapacity)
430                                        {
431                                                PAGEITEM* pPageItem = (PAGEITEM*) (pPageHeader + 1) + pPageHeader->nItemCount;
432                                                pPageItem->nFlags = PageItem.nFlags & PAGEITEMFLAG_TYPE_MASK;
433                                                pPageItem->nThreadIdentifier = GetCurrentThreadId();
434                                                pPageItem->nFilterIdentifier = nFilterIdentifier;
435                                                wcsncpy_s(pPageItem->pszFilterName, sFilterName, _TRUNCATE);
436                                                if(pszStreamName)
437                                                        wcsncpy_s(pPageItem->pszStreamName, pszStreamName, _TRUNCATE);
438                                                else
439                                                        *pPageItem->pszStreamName = 0;
440                                                pPageItem->nTime = nTime;
441                                                pPageItem->Data = PageItem.Data;
442                                                if(pszComment)
443                                                        wcsncpy_s(pPageItem->pszComment, pszComment, _TRUNCATE);
444                                                else
445                                                        *pPageItem->pszComment = 0;
446                                                pPageHeader->nItemCount++;
447                                                return;
448                                        }
449                                        m_ItemList.GetTail().m_bActive = FALSE;
450                                }
451                                const POSITION Position = m_ItemList.AddTail();
452                                _ATLTRY
453                                {
454                                        CItem& Item = m_ItemList.GetAt(Position);
455                                        Pages.CreatePage(Item.m_nPageIdentifier, Item.m_Mutex, Item.m_FileMapping);
456                                        Item.m_bActive = TRUE;
457                                }
458                                _ATLCATCHALL()
459                                {
460                                        m_ItemList.RemoveAt(Position);
461                                        _ATLRETHROW;
462                                }
463                        }
464                }
465        };
466
467public:
468// CMediaSampleTraceBase
469};
470
471////////////////////////////////////////////////////////////
472// CMediaSampleTrace
473
474class ATL_NO_VTABLE CMediaSampleTrace :
475        public CComObjectRootEx<CComMultiThreadModelNoCS>,
476        public CComCoClass<CMediaSampleTrace>,// &__uuidof(MediaSampleTrace)>,
477        //public IProvideClassInfo2Impl<&__uuidof(MediaSampleTrace), &IID_NULL>,
478        public IMediaSampleTrace,
479        public CMediaSampleTraceBase
480{
481public:
482        //enum { IDR = IDR_MediaSampleTrace };
483
484DECLARE_NO_REGISTRY() //DECLARE_REGISTRY_RESOURCEID(IDR)
485
486BEGIN_COM_MAP(CMediaSampleTrace)
487        COM_INTERFACE_ENTRY(IMediaSampleTrace)
488        //COM_INTERFACE_ENTRY(IProvideClassInfo2)
489        //COM_INTERFACE_ENTRY(IProvideClassInfo)
490END_COM_MAP()
491
492public:
493
494private:
495        //mutable CRoCriticalSection m_DataCriticalSection;
496        UINT_PTR m_nFilterGraphIdentifier;
497        CStringW m_sFilterGraphName;
498        CPages m_Pages;
499        CPage m_Page;
500
501public:
502// CMediaSampleTrace
503        CMediaSampleTrace()
504        {
505                _Z4_THIS();
506        }
507        ~CMediaSampleTrace()
508        {
509                _Z4_THIS();
510        }
511        VOID Initialize(ISpy* pSpy)
512        {
513                _A(pSpy);
514                CComBSTR sName;
515                __C(pSpy->get_FriendlyName(&sName));
516                const CComQIPtr<IFilterGraph2> pFilterGraph2 = pSpy;
517                _A(pFilterGraph2);
518                //CRoCriticalSectionLock DataLock(m_DataCriticalSection);
519                m_nFilterGraphIdentifier = (UINT_PTR) (IFilterGraph2*) pFilterGraph2;
520                m_sFilterGraphName = CStringW(sName);
521                m_Pages.Initialize((UINT64) m_nFilterGraphIdentifier, m_sFilterGraphName);
522                // NOTE: We might prefer to let the pages leak away to outlive the filter graph itself...
523                AddRef();
524        }
525        static CStringW GetFilterName(IUnknown* pBaseFilterUnknown)
526        {
527                CStringW sFilterName;
528                const CComQIPtr<IBaseFilter> pBaseFilter = pBaseFilterUnknown;
529                if(pBaseFilter)
530                        sFilterName = _FilterGraphHelper::GetFilterName(pBaseFilter);
531                return sFilterName;
532        }
533
534// IMediaSampleTrace
535        STDMETHOD(RegisterNewSegment)(IUnknown* pBaseFilterUnknown, const WCHAR* pszStreamName, LONGLONG nStartTime, LONGLONG nStopTime, DOUBLE fRate, const WCHAR* pszComment)
536        {
537                _Z5(atlTraceCOM, 5, _T("this 0x%p, pBaseFilterUnknown 0x%p, pszStreamName \"%s\", nStartTime %I64d\n"), this, pBaseFilterUnknown, CString(pszStreamName), nStartTime);
538                _ATLTRY
539                {
540                        PAGEITEM PageItem;
541                        PageItem.nFlags = PAGEITEMFLAG_NEWSEGMENT;
542                        PageItem.Data.NewSegment.nStartTime = nStartTime;
543                        PageItem.Data.NewSegment.nStopTime = nStopTime;
544                        PageItem.Data.NewSegment.fRate = fRate;
545                        m_Page.Register(m_Pages, (UINT_PTR) pBaseFilterUnknown, GetFilterName(pBaseFilterUnknown), pszStreamName, PageItem, pszComment);
546                }
547                _ATLCATCH(Exception)
548                {
549                        _C(Exception);
550                }
551                return S_OK;
552        }
553        STDMETHOD(RegisterMediaSample)(IUnknown* pBaseFilterUnknown, const WCHAR* pszStreamName, const BYTE* pnSamplePropertiesData, const WCHAR* pszComment)
554        {
555                _Z5(atlTraceCOM, 5, _T("this 0x%p, pBaseFilterUnknown 0x%p, pszStreamName \"%s\", pnSamplePropertiesData 0x%p\n"), this, pBaseFilterUnknown, CString(pszStreamName), pnSamplePropertiesData);
556                _ATLTRY
557                {
558                        __D(pnSamplePropertiesData, E_POINTER);
559                        PAGEITEM PageItem;
560                        PageItem.nFlags = PAGEITEMFLAG_MEDIASAMPLE;
561                        PageItem.Data.MediaSample.Properties = *((const AM_SAMPLE2_PROPERTIES*) pnSamplePropertiesData);
562                        m_Page.Register(m_Pages, (UINT_PTR) pBaseFilterUnknown, GetFilterName(pBaseFilterUnknown), pszStreamName, PageItem, pszComment);
563                }
564                _ATLCATCH(Exception)
565                {
566                        _C(Exception);
567                }
568                return S_OK;
569        }
570        STDMETHOD(RegisterEndOfStream)(IUnknown* pBaseFilterUnknown, const WCHAR* pszStreamName, const WCHAR* pszComment)
571        {
572                _Z5(atlTraceCOM, 5, _T("this 0x%p, pBaseFilterUnknown 0x%p, pszStreamName \"%s\"\n"), this, pBaseFilterUnknown, CString(pszStreamName));
573                _ATLTRY
574                {
575                        PAGEITEM PageItem;
576                        PageItem.nFlags = PAGEITEMFLAG_ENDOFSTREAM;
577                        m_Page.Register(m_Pages, (UINT_PTR) pBaseFilterUnknown, GetFilterName(pBaseFilterUnknown), pszStreamName, PageItem, pszComment);
578                }
579                _ATLCATCH(Exception)
580                {
581                        _C(Exception);
582                }
583                return S_OK;
584        }
585        STDMETHOD(RegisterComment)(IUnknown* pBaseFilterUnknown, const WCHAR* pszStreamName, const WCHAR* pszComment)
586        {
587                _Z5(atlTraceCOM, 5, _T("this 0x%p, pBaseFilterUnknown 0x%p, pszStreamName \"%s\", pszComment \"%s\"\n"), this, pBaseFilterUnknown, CString(pszStreamName), CString(pszComment));
588                _ATLTRY
589                {
590                        PAGEITEM PageItem;
591                        PageItem.nFlags = PAGEITEMFLAG_COMMENT;
592                        m_Page.Register(m_Pages, (UINT_PTR) pBaseFilterUnknown, GetFilterName(pBaseFilterUnknown), pszStreamName, PageItem, pszComment);
593                }
594                _ATLCATCH(Exception)
595                {
596                        _C(Exception);
597                }
598                return S_OK;
599        }
600};
601
602//OBJECT_ENTRY_AUTO(__uuidof(MediaSampleTrace), CMediaSampleTrace)
603
604////////////////////////////////////////////////////////////
605// CMediaSampleTracePropertySheet
606
607class CMediaSampleTracePropertySheet :
608        public CSizablePropertySheetT<CMediaSampleTracePropertySheet>,
609        public CMediaSampleTraceBase
610{
611public:
612
613BEGIN_MSG_MAP_EX(CMediaSampleTracePropertySheet)
614        CHAIN_MSG_MAP(CSizablePropertySheet)
615        MSG_WM_SYSCOMMAND(OnSysCommand)
616END_MSG_MAP()
617
618public:
619
620        ////////////////////////////////////////////////////////
621        // CMediaSamplePropertyPage
622
623        class CMediaSamplePropertyPage :
624                public CPropertyPageT<CMediaSamplePropertyPage>,
625                public CPropertyPageWithAcceleratorsT<CMediaSamplePropertyPage>,
626                public CDialogResize<CMediaSamplePropertyPage>
627        {
628        public:
629                enum { IDD = IDD_MEDIASAMPLETRACE_MEDIASAMPLE_PROPERTYPAGE };
630
631        BEGIN_MSG_MAP_EX(CMediaSamplePropertyPage)
632                CHAIN_MSG_MAP(CPropertyPage)
633                CHAIN_MSG_MAP(CPropertyPageWithAccelerators)
634                CHAIN_MSG_MAP(CDialogResize<CMediaSamplePropertyPage>)
635                MSG_WM_INITDIALOG(OnInitDialog)
636                MSG_LVN_GETDISPINFO(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_LIST, OnListViewGetDispInfo)
637                MSG_LVN_GETINFOTIP(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_LIST, OnListViewGetInfoTip)
638                MSG_WM_CONTEXTMENU(OnContextMenu)
639                COMMAND_ID_HANDLER_EX(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_REFRESH, OnRefresh)
640                COMMAND_ID_HANDLER_EX(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_COPYTOCLIPBOARD, OnCopyToClipboard)
641                COMMAND_ID_HANDLER_EX(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_SAVETOFILE, OnSaveToFile)
642                COMMAND_ID_HANDLER_EX(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_RESETDATA, OnResetData)
643                COMMAND_ID_HANDLER_EX(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_OPENFILTERGRAPHLIST, OnOpenFilterGraphList)
644                REFLECT_NOTIFICATIONS()
645        END_MSG_MAP()
646
647        BEGIN_DLGRESIZE_MAP(CMediaSamplePropertyPage)
648                DLGRESIZE_CONTROL(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_INTRODUCTION, DLSZ_SIZE_X)
649                DLGRESIZE_CONTROL(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_LIST, DLSZ_SIZE_X | DLSZ_SIZE_Y)
650                DLGRESIZE_CONTROL(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_REFRESH, DLSZ_MOVE_Y)
651                DLGRESIZE_CONTROL(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_COPYTOCLIPBOARD, DLSZ_MOVE_Y)
652                DLGRESIZE_CONTROL(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_SAVETOFILE, DLSZ_MOVE_Y)
653        END_DLGRESIZE_MAP()
654
655        private:
656                CMediaSampleTracePropertySheet& m_PropertySheet;
657                CRoHyperStatic m_IntroductionStatic;
658                CRoListViewT<CData::CItem, CRoListControlDataTraitsT> m_ListView;
659                CRoHyperStatic m_RefreshStatic;
660                CRoHyperStatic m_CopyToClipboardStatic;
661                CRoHyperStatic m_SaveToFileStatic;
662                CRoMapT<INT, BOOL> m_ChangeMap;
663                CPages m_Pages;
664
665        public:
666        // CMediaSamplePropertyPage
667                CMediaSamplePropertyPage(CMediaSampleTracePropertySheet* pPropertySheet) :
668                        m_PropertySheet(*pPropertySheet)
669                {
670                }
671                VOID UpdateControls()
672                {
673                }
674                VOID UpdateListView()
675                {
676                        CWindowRedraw ListViewRedraw(m_ListView);
677                        m_ListView.DeleteAllItems();
678                        CPages Pages;
679                        if(Pages.Initialize())
680                        {
681                                CData Data;
682                                Pages.GetData(Data);
683                                Data.Sort();
684                                INT nItem = 0;
685                                for(auto&& Item: Data.m_ItemArray)
686                                        m_ListView.InsertItem(nItem++, Item);
687                        }
688                }
689                static CString FormatTime(UINT64 nTime)
690                {
691                        SYSTEMTIME Time;
692                        FileTimeToSystemTime(&reinterpret_cast<const FILETIME&>(nTime), &Time);
693                        return AtlFormatString(_T("%02d:%02d:%02d.%03d"), Time.wHour, Time.wMinute, Time.wSecond, Time.wMilliseconds);
694                }
695                CStringA CreateText()
696                {
697                        CString sText;
698                        #pragma region Header
699                        LPCTSTR g_ppszHeader[] = 
700                        {
701                                _T("Time"),
702                                _T("Process Identifier"),
703                                _T("Thread Identifier"),
704                                _T("Filter Graph Identifier"),
705                                _T("Filter Graph Name"),
706                                _T("Filter Identifier"),
707                                _T("Filter Name"),
708                                _T("Stream"),
709                                _T("Type"),
710                                _T("Media Sample Flags"),
711                                _T("Start Time"),
712                                _T("Stop Time"),
713                                _T("Length Time"),
714                                _T("Data Size"),
715                                _T("Comment"),
716                        };
717                        sText += _StringHelper::Join(g_ppszHeader, _T("\t")) + _T("\r\n");
718                        #pragma endregion
719                        for(INT nItem = 0; nItem < m_ListView.GetItemCount(); nItem++)
720                        {
721                                const CData::CItem& Item = m_ListView.GetItemData(nItem);
722                                CRoArrayT<CString> Array;
723                                Array.Add(FormatTime(Item.m_PageItem.nTime));
724                                Array.Add(AtlFormatString(_T("%d"), Item.m_Item.nProcessIdentifier));
725                                Array.Add(AtlFormatString(_T("%d"), Item.m_PageItem.nThreadIdentifier));
726                                Array.Add(AtlFormatString(_T("0x%p"), Item.m_Item.nFilterGraphIdentifier));
727                                Array.Add(CString(Item.m_Item.pszFilterGraphName));
728                                Array.Add(AtlFormatString(_T("0x%p"), Item.m_PageItem.nFilterIdentifier));
729                                Array.Add(CString(Item.m_PageItem.pszFilterName));
730                                Array.Add(CString(Item.m_PageItem.pszStreamName));
731                                Array.Add(Item.FormatType());
732                                switch(Item.m_PageItem.nFlags & PAGEITEMFLAG_TYPE_MASK)
733                                {
734                                case PAGEITEMFLAG_NEWSEGMENT:
735                                        Array.Add(_T(""));
736                                        Array.Add(AtlFormatString(_T("%I64d"), Item.m_PageItem.Data.NewSegment.nStartTime));
737                                        if(Item.m_PageItem.Data.NewSegment.nStopTime < LLONG_MAX)
738                                                Array.Add(AtlFormatString(_T("%I64d"), Item.m_PageItem.Data.NewSegment.nStopTime));
739                                        //Item.m_PageItem.Data.NewSegment.fRate
740                                        break;
741                                case PAGEITEMFLAG_MEDIASAMPLE:
742                                        Array.Add(_FilterGraphHelper::FormatSampleFlags(Item.m_PageItem.Data.MediaSample.Properties.dwSampleFlags));
743                                        if(Item.m_PageItem.Data.MediaSample.Properties.dwSampleFlags & AM_SAMPLE_TIMEVALID)
744                                        {
745                                                Array.Add(AtlFormatString(_T("%I64d"), Item.m_PageItem.Data.MediaSample.Properties.tStart));
746                                                if(Item.m_PageItem.Data.MediaSample.Properties.dwSampleFlags & AM_SAMPLE_STOPVALID)
747                                                {
748                                                        Array.Add(AtlFormatString(_T("%I64d"), Item.m_PageItem.Data.MediaSample.Properties.tStop));
749                                                        Array.Add(AtlFormatString(_T("%I64d"), Item.m_PageItem.Data.MediaSample.Properties.tStop - Item.m_PageItem.Data.MediaSample.Properties.tStart));
750                                                }
751                                        }
752                                        while(Array.GetCount() < 13)
753                                                Array.Add(_T(""));
754                                        Array.Add(AtlFormatString(_T("%d"), Item.m_PageItem.Data.MediaSample.Properties.lActual));
755                                        break;
756                                case PAGEITEMFLAG_ENDOFSTREAM:
757                                case PAGEITEMFLAG_COMMENT:
758                                        break;
759                                default:
760                                        _A(FALSE);
761                                }
762                                if(*Item.m_PageItem.pszComment)
763                                {
764                                        while(Array.GetCount() < 14)
765                                                Array.Add(_T(""));
766                                        Array.Add(CString(Item.m_PageItem.pszComment));
767                                }
768                                sText += _StringHelper::Join(Array, _T("\t"));
769                                sText += _T("\r\n");
770                        }
771                        return CStringA(sText);
772                }
773
774        // Window Message Handler
775                LRESULT OnInitDialog(HWND, LPARAM)
776                {
777                        _ATLTRY
778                        {
779                                CWaitCursor WaitCursor;
780                                _W(m_IntroductionStatic.SubclassWindow(GetDlgItem(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_INTRODUCTION)));
781                                m_ListView.Initialize(GetDlgItem(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_LIST));
782                                _W(m_RefreshStatic.SubclassWindow(GetDlgItem(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_REFRESH)));
783                                m_RefreshStatic.SetExtendedStyle(CRoHyperStatic::CS_ANCHORCLICKCOMMAND);
784                                _W(m_CopyToClipboardStatic.SubclassWindow(GetDlgItem(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_COPYTOCLIPBOARD)));
785                                m_CopyToClipboardStatic.SetExtendedStyle(CRoHyperStatic::CS_ANCHORCLICKCOMMAND);
786                                _W(m_SaveToFileStatic.SubclassWindow(GetDlgItem(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_SAVETOFILE)));
787                                m_SaveToFileStatic.SetExtendedStyle(CRoHyperStatic::CS_ANCHORCLICKCOMMAND);
788                                CRoHyperStatic::ArrangeHorizontally(&m_RefreshStatic, &m_CopyToClipboardStatic, &m_SaveToFileStatic, NULL);
789                                DlgResize_Init(FALSE, FALSE);
790                                _ATLTRY
791                                {
792                                        // NOTE: This forces the global file mapping open referenced by UI
793                                        // WARN: This is however incomplete since we only keep master mapping and process mappings are gone once the process is gone
794                                        m_Pages.Initialize(TRUE);
795                                }
796                                _ATLCATCHALL()
797                                {
798                                        _Z_EXCEPTION();
799                                }
800                                UpdateListView();
801                                m_ChangeMap.RemoveAll();
802                                UpdateControls();
803                                #pragma region Default Property Sheet Size
804                                CRect Position;
805                                _W(m_PropertySheet.GetWindowRect(Position));
806                                Position.InflateRect(6 * Position.Width() / 8, 5 * Position.Width() / 8);
807                                CSize ScreenExtent(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
808                                ScreenExtent.cx -= ScreenExtent.cx / 8;
809                                ScreenExtent.cy -= ScreenExtent.cy / 8;
810                                if(Position.Width() > ScreenExtent.cx)
811                                        Position.right = Position.left + ScreenExtent.cx;
812                                if(Position.Height() > ScreenExtent.cy)
813                                        Position.bottom = Position.top + ScreenExtent.cy;
814                                _W(m_PropertySheet.MoveWindow(Position));
815                                _W(m_PropertySheet.CenterWindow());
816                                #pragma endregion
817                        }
818                        _ATLCATCHALL()
819                        {
820                                for(CWindow Window = GetWindow(GW_CHILD); Window.IsWindow(); Window = Window.GetWindow(GW_HWNDNEXT))
821                                        Window.EnableWindow(FALSE);
822                                _ATLRETHROW;
823                        }
824                        return TRUE;
825                }
826                LRESULT OnTranslateAccelerator(MSG* pMessage)
827                {
828                        return TranslateAccelerator(m_hWnd, m_hAccelerators, pMessage) ? PSNRET_MESSAGEHANDLED : PSNRET_NOERROR;
829                }
830                LRESULT OnListViewGetDispInfo(NMLVDISPINFO* pHeader)
831                {
832                        const CData::CItem& Item = m_ListView.DataFromParameter(pHeader->item.lParam);
833                        if(pHeader->item.mask & LVIF_TEXT)
834                        {
835                                CString& sTextBuffer = m_ListView.GetTextBufferString(TRUE);
836                                switch(pHeader->item.iSubItem)
837                                {
838                                case 1: // Process
839                                        sTextBuffer = AtlFormatString(_T("%d"), (UINT_PTR) Item.m_Item.nProcessIdentifier);
840                                        break;
841                                case 2: // Thread
842                                        sTextBuffer = AtlFormatString(_T("%d"), (UINT_PTR) Item.m_PageItem.nThreadIdentifier);
843                                        break;
844                                case 3: // Filter Graph
845                                        sTextBuffer = AtlFormatString(_T("0x%p %ls"), (UINT_PTR) Item.m_Item.nFilterGraphIdentifier, Item.m_Item.pszFilterGraphName);
846                                        break;
847                                case 4: // Filter
848                                        sTextBuffer = AtlFormatString(_T("0x%p %ls"), (UINT_PTR) Item.m_PageItem.nFilterIdentifier, Item.m_PageItem.pszFilterName);
849                                        break;
850                                case 5: // Stream
851                                        sTextBuffer = AtlFormatString(_T("%ls"), Item.m_PageItem.pszStreamName);
852                                        break;
853                                case 6: // Type
854                                        sTextBuffer = Item.FormatType();
855                                        break;
856                                case 7: // Flags
857                                        if((Item.m_PageItem.nFlags & PAGEITEMFLAG_TYPE_MASK) == PAGEITEMFLAG_MEDIASAMPLE)
858                                                sTextBuffer = _FilterGraphHelper::FormatSampleFlags(Item.m_PageItem.Data.MediaSample.Properties.dwSampleFlags);
859                                        break;
860                                case 8: // Start Time
861                                        if((Item.m_PageItem.nFlags & PAGEITEMFLAG_TYPE_MASK) == PAGEITEMFLAG_NEWSEGMENT)
862                                        {
863                                                sTextBuffer = _FilterGraphHelper::FormatReferenceTime(Item.m_PageItem.Data.NewSegment.nStartTime);
864                                        } else
865                                        if((Item.m_PageItem.nFlags & PAGEITEMFLAG_TYPE_MASK) == PAGEITEMFLAG_MEDIASAMPLE)
866                                        {
867                                                if(Item.m_PageItem.Data.MediaSample.Properties.dwSampleFlags & AM_SAMPLE_TIMEVALID)
868                                                        sTextBuffer = _FilterGraphHelper::FormatReferenceTime(Item.m_PageItem.Data.MediaSample.Properties.tStart);
869                                        }
870                                        break;
871                                case 9: // Stop Time
872                                        if((Item.m_PageItem.nFlags & PAGEITEMFLAG_TYPE_MASK) == PAGEITEMFLAG_NEWSEGMENT)
873                                        {
874                                                if(Item.m_PageItem.Data.NewSegment.nStopTime < LLONG_MAX)
875                                                        sTextBuffer = _FilterGraphHelper::FormatReferenceTime(Item.m_PageItem.Data.NewSegment.nStopTime);
876                                        } else
877                                        if((Item.m_PageItem.nFlags & PAGEITEMFLAG_TYPE_MASK) == PAGEITEMFLAG_MEDIASAMPLE)
878                                        {
879                                                if((Item.m_PageItem.Data.MediaSample.Properties.dwSampleFlags & (AM_SAMPLE_TIMEVALID | AM_SAMPLE_STOPVALID)) == (AM_SAMPLE_TIMEVALID | AM_SAMPLE_STOPVALID))
880                                                        sTextBuffer = _FilterGraphHelper::FormatReferenceTime(Item.m_PageItem.Data.MediaSample.Properties.tStop);
881                                        }
882                                        break;
883                                case 10: // Comment
884                                        sTextBuffer = CString(Item.m_PageItem.pszComment);
885                                        break;
886                                default: // Time
887                                        sTextBuffer = FormatTime(Item.m_PageItem.nTime);
888                                }
889                                pHeader->item.pszText = m_ListView.GetTextBuffer();
890                        }
891                        return 0;
892                }
893                LRESULT OnListViewGetInfoTip(NMLVGETINFOTIP* pHeader)
894                {
895                        const CData::CItem& Item = m_ListView.GetItemData(pHeader->iItem);
896                        CString& sTextBuffer = m_ListView.GetTextBufferString(TRUE);
897                        sTextBuffer.AppendFormat(_T("Time: %s\r\n"), FormatTime(Item.m_PageItem.nTime));
898                        sTextBuffer.AppendFormat(_T("Process: %d\r\n"), (UINT_PTR) Item.m_Item.nProcessIdentifier);
899                        sTextBuffer.AppendFormat(_T("Thread: %d\r\n"), (UINT_PTR) Item.m_PageItem.nThreadIdentifier);
900                        sTextBuffer.AppendFormat(_T("Filter Graph: 0x%p %ls\r\n"), (UINT_PTR) Item.m_Item.nFilterGraphIdentifier, Item.m_Item.pszFilterGraphName);
901                        sTextBuffer.AppendFormat(_T("Filter: 0x%p %ls\r\n"), (UINT_PTR) Item.m_PageItem.nFilterIdentifier, Item.m_PageItem.pszFilterName);
902                        sTextBuffer.AppendFormat(_T("Stream: %ls\r\n"), Item.m_PageItem.pszStreamName);
903                        sTextBuffer.AppendFormat(_T("Type: %s\r\n"), Item.FormatType());
904                        switch(Item.m_PageItem.nFlags & PAGEITEMFLAG_TYPE_MASK)
905                        {
906                        case PAGEITEMFLAG_NEWSEGMENT:
907                                sTextBuffer.AppendFormat(_T("Start Time: %s\r\n"), _FilterGraphHelper::FormatReferenceTime(Item.m_PageItem.Data.NewSegment.nStartTime));
908                                if(Item.m_PageItem.Data.NewSegment.nStopTime < LLONG_MAX)
909                                        sTextBuffer.AppendFormat(_T("Stop Time: %s\r\n"), _FilterGraphHelper::FormatReferenceTime(Item.m_PageItem.Data.NewSegment.nStopTime));
910                                sTextBuffer.AppendFormat(_T("Rate: %.3f\r\n"), Item.m_PageItem.Data.NewSegment.fRate);
911                                break;
912                        case PAGEITEMFLAG_MEDIASAMPLE:
913                                sTextBuffer.AppendFormat(_T("Sample Flags: %s\r\n"), _FilterGraphHelper::FormatSampleFlags(Item.m_PageItem.Data.MediaSample.Properties.dwSampleFlags));
914                                if(Item.m_PageItem.Data.MediaSample.Properties.dwSampleFlags & AM_SAMPLE_TIMEVALID)
915                                {
916                                        sTextBuffer.AppendFormat(_T("Start Time: %s\r\n"), _FilterGraphHelper::FormatReferenceTime(Item.m_PageItem.Data.MediaSample.Properties.tStart));
917                                        if(Item.m_PageItem.Data.MediaSample.Properties.dwSampleFlags & AM_SAMPLE_STOPVALID)
918                                        {
919                                                sTextBuffer.AppendFormat(_T("Stop Time: %s\r\n"), _FilterGraphHelper::FormatReferenceTime(Item.m_PageItem.Data.MediaSample.Properties.tStop));
920                                                sTextBuffer.AppendFormat(_T("Length Time: %s\r\n"), _FilterGraphHelper::FormatReferenceTime(Item.m_PageItem.Data.MediaSample.Properties.tStop - Item.m_PageItem.Data.MediaSample.Properties.tStart));
921                                        }
922                                }
923                                sTextBuffer.AppendFormat(_T("Data Size: %s\r\n"), _StringHelper::FormatNumber(Item.m_PageItem.Data.MediaSample.Properties.lActual));
924                                break;
925                        case PAGEITEMFLAG_ENDOFSTREAM:
926                        case PAGEITEMFLAG_COMMENT:
927                                break;
928                        default:
929                                _A(FALSE);
930                        }
931                        if(*Item.m_PageItem.pszComment)
932                                sTextBuffer.AppendFormat(_T("\r\n") _T("%ls\r\n"), Item.m_PageItem.pszComment);
933                        sTextBuffer.TrimRight(_T("\t\n\r ."));
934                        #pragma region Clipboard Copy
935                        if(GetKeyState(VK_CONTROL) < 0 && GetKeyState(VK_SHIFT) < 0)
936                                _ATLTRY
937                                {
938                                        SetClipboardText(m_hWnd, sTextBuffer);
939                                        MessageBeep(MB_OK);
940                                }
941                                _ATLCATCHALL()
942                                {
943                                        _Z_EXCEPTION();
944                                        MessageBeep(MB_ICONERROR);
945                                }
946                        #pragma endregion
947                        _tcsncpy_s(pHeader->pszText, pHeader->cchTextMax, m_ListView.GetTextBuffer(), _TRUNCATE);
948                        return 0;
949                }
950                LRESULT OnContextMenu(CWindow, CPoint Position)
951                {
952                        CMenu ContainerMenu = AtlLoadMenu(IDD);
953                        CMenuHandle Menu = ContainerMenu.GetSubMenu(0);
954                        Menu.TrackPopupMenu(TPM_RIGHTBUTTON | TPM_LEFTALIGN | TPM_TOPALIGN, Position.x, Position.y, m_hWnd); 
955                        return 0;
956                }
957                LRESULT OnRefresh(UINT, INT, HWND)
958                {
959                        CWaitCursor WaitCursor;
960                        UpdateListView();
961                        return 0;
962                }
963                LRESULT OnCopyToClipboard(UINT, INT, HWND)
964                {
965                        CWaitCursor WaitCursor;
966                        SetClipboardText(m_hWnd, CreateText());
967                        MessageBeep(MB_OK);
968                        return 0;
969                }
970                LRESULT OnSaveToFile(UINT, INT, HWND)
971                {
972                        static const COMDLG_FILTERSPEC g_pFilter[] = 
973                        {
974                                { _T("TSV Files"), _T("*.tsv") },
975                                { _T("TSV Files, Bzip2 Compressed"), _T("*.tsv.bz2") },
976                                { _T("All Files"), _T("*.*") },
977                        };
978                        CPath sPath = _CommonDialogHelper::QuerySavePath(m_hWnd, g_pFilter, _T("tsv"), _T("Media Sample Trace.tsv"));
979                        if(!_tcslen(sPath))
980                                return 0;
981                        CWaitCursor WaitCursor;
982                        const CStringA sText = CreateText();
983                        LPCTSTR pszExtension = FindExtension(sPath);
984                        CAtlFile File;
985                        __C(File.Create(sPath, GENERIC_WRITE, FILE_SHARE_READ, CREATE_ALWAYS));
986                        _ATLTRY
987                        {
988                                if(_tcsicmp(pszExtension, _T(".bz2")) == 0)
989                                {
990                                        CLocalObjectPtr<CBzip2Item> pItem;
991                                        pItem->SetRawData((const BYTE*) (LPCSTR) sText, sText.GetLength());
992                                        CHeapPtr<BYTE> pnData;
993                                        SIZE_T nDataSize;
994                                        pItem->GetData(pnData, nDataSize);
995                                        __C(File.Write(pnData, (DWORD) nDataSize));
996                                } else
997                                {
998                                        __C(File.Write(sText, sText.GetLength() * sizeof (CHAR)));
999                                }
1000                        }
1001                        _ATLCATCHALL()
1002                        {
1003                                File.Close();
1004                                DeleteFile(sPath);
1005                                _ATLRETHROW;
1006                        }
1007                        return 0;
1008                }
1009                LRESULT OnResetData(UINT, INT, HWND)
1010                {
1011                        CWaitCursor WaitCursor;
1012                        m_Pages.ResetData();
1013                        UpdateListView();
1014                        return 0;
1015                }
1016                LRESULT OnOpenFilterGraphList(UINT, INT, HWND)
1017                {
1018                        CLocalObjectPtr<CFilterGraphHelper> pFilterGraphHelper;
1019                        pFilterGraphHelper->DoFilterGraphListModal((LONG) (LONG_PTR) m_hWnd);
1020                        return 0;
1021                }
1022        };
1023
1024private:
1025        CMediaSamplePropertyPage m_MediaSamplePropertyPage;
1026
1027public:
1028// CMediaSampleTracePropertySheet
1029        CMediaSampleTracePropertySheet() :
1030                CSizablePropertySheetT<CMediaSampleTracePropertySheet>(IDS_MEDIASAMPLETRACE_MEDIASAMPLE_PROPERTYSHEETCAPTION),
1031                m_MediaSamplePropertyPage(this)
1032        {
1033                AddPage(m_MediaSamplePropertyPage);
1034        }
1035        BOOL SetInitialPosition()
1036        {
1037                if(!__super::SetInitialPosition())
1038                        return FALSE;
1039                SetIcon(AtlLoadIconImage(IDI_MODULE, LR_DEFAULTCOLOR, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON)), TRUE);
1040                SetIcon(AtlLoadIconImage(IDI_MODULE, LR_DEFAULTCOLOR, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON)), FALSE);
1041                CAboutDialog::UpdateCaption(*this);
1042                #pragma region System Menu
1043                CMenuHandle Menu = GetSystemMenu(FALSE);
1044                _W(Menu.AppendMenu(MF_SEPARATOR));
1045                _W(Menu.AppendMenu(MF_STRING, ID_APP_ABOUT, _T("&About...")));
1046                #pragma endregion
1047                return TRUE;
1048        }
1049
1050// Window Message Handler
1051        LRESULT OnSysCommand(UINT nCommand, CPoint)
1052        {
1053                switch(nCommand)
1054                {
1055                case ID_APP_ABOUT:
1056                        {
1057                                CAboutDialog Dialog;
1058                                Dialog.DoModal(m_hWnd);
1059                        }
1060                        break;
1061                default:
1062                        SetMsgHandled(FALSE);
1063                }
1064                return 0;
1065        }
1066};
1067
1068// TODO: Double-Click on media trace entry opens graph
Note: See TracBrowser for help on using the repository browser.