A Fast Bresenham Type Algorithm For Drawing Ellipses by John Kennedy
[xy_vsfilter.git] / src / apps / mplayerc / ConvertDlg.cpp
blob258854500f96bbcb96e04fe1dbbc9fe990095cc8
1 /*
2 * Copyright (C) 2003-2006 Gabest
3 * http://www.gabest.org
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GNU Make; see the file COPYING. If not, write to
17 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18 * http://www.gnu.org/copyleft/gpl.html
22 // ConvertDlg.cpp : implementation file
25 #include "stdafx.h"
26 #include <mmreg.h>
27 #include "mplayerc.h"
28 #include "..\..\filters\filters.h"
29 #include "..\..\..\include\moreuuids.h"
30 #include "FGManager.h"
31 #include "ConvertPropsDlg.h"
32 #include "ConvertResDlg.h"
33 #include "ConvertChapDlg.h"
34 #include "ConvertDlg.h"
36 // TODO: subtitle source filter for vobsub
38 // CConvertDlg dialog
40 CConvertDlg::CConvertDlg(CWnd* pParent /*=NULL*/)
41 : CResizableDialog(CConvertDlg::IDD, pParent)
42 , m_fn(_T(""))
46 CConvertDlg::~CConvertDlg()
50 void CConvertDlg::AddFile(CString fn)
52 CString protocol;
54 int i = fn.Find(_T("://"));
55 if(i > 0)
57 CString url = fn.Mid(i);
58 CPath path(fn.Left(i));
59 path.StripPath();
60 protocol = (LPCTSTR)path;
61 fn = (LPCTSTR)path + url;
64 CComPtr<IBaseFilter> pBF;
65 if(FAILED(m_pGB->AddSourceFilter(CStringW(fn), CStringW(fn), &pBF)))
66 return;
68 int nConnected = 0;
69 BeginEnumPins(pBF, pEP, pPin)
70 if(S_OK == m_pGB->ConnectFilter(pPin, m_pMux)) nConnected++;
71 EndEnumPins
72 if(!nConnected) {MessageBeep(-1); DeleteFilter(pBF); return;}
74 if(m_tree.GetCount() == 0)
76 if(CComQIPtr<IDSMPropertyBag> pPB = m_pMux)
77 pPB->DelAllProperties();
79 CString ext(_T(".dsm"));
81 if(!protocol.IsEmpty())
83 m_fn = protocol + ext;
85 else
87 CPath p(fn);
88 if(ext.CompareNoCase(p.GetExtension()) == 0)
89 ext = _T(" (remuxed)") + ext;
90 p.RemoveExtension();
91 m_fn = (LPCTSTR)p + ext;
94 UpdateData(FALSE);
97 CTreeItemFile* t = new CTreeItemFile(fn, pBF, m_tree, NULL);
99 AddFilter(*t, pBF);
101 m_tree.Expand(*t, TVE_EXPAND);
102 m_tree.EnsureVisible(*t);
105 bool CConvertDlg::ConvertFile(LPCTSTR fn, IPin* pPin)
107 OAFilterState fs;
108 if(!m_pMC || FAILED(m_pMC->GetState(0, &fs)) || fs != State_Stopped)
109 return false;
111 m_pGB->NukeDownstream(m_pMux);
113 CComPtr<IBaseFilter> pFW;
114 pFW.CoCreateInstance(CLSID_FileWriter);
115 CComQIPtr<IFileSinkFilter2> pFSF = pFW;
117 if(pPin)
119 CComQIPtr<IBaseMuxerRelatedPin> pRP = pPin;
120 if(!pRP) return false;
122 pPin = pRP->GetRelatedPin();
124 else
126 pPin = GetFirstPin(m_pMux, PINDIR_OUTPUT);
129 if(!pPin || !pFSF
130 || FAILED(m_pGB->AddFilter(pFW, NULL))
131 || FAILED(pFSF->SetFileName(CStringW(fn), NULL))
132 || FAILED(pFSF->SetMode(AM_FILE_OVERWRITE))
133 || FAILED(m_pGB->ConnectDirect(pPin, GetFirstPin(pFW), NULL)))
135 m_pGB->RemoveFilter(pFW);
136 return false;
139 if(m_pMS)
141 LONGLONG pos = 0;
142 m_pMS->SetPositions(&pos, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning);
145 if(CComQIPtr<IDSMPropertyBag> pPB = m_pMux)
147 pPB->SetProperty(L"APPL", L"Media Player Classic");
150 if(CComQIPtr<IDSMResourceBag> pRB = m_pMux)
152 pRB->ResRemoveAll(0);
153 POSITION pos = m_pTIs.GetHeadPosition();
154 while(pos)
156 if(CTreeItemResource* t2 = dynamic_cast<CTreeItemResource*>((CTreeItem*)m_pTIs.GetNext(pos)))
157 pRB->ResAppend(
158 t2->m_res.name, t2->m_res.desc, t2->m_res.mime,
159 t2->m_res.data.GetData(), t2->m_res.data.GetCount(),
160 NULL);
164 if(CComQIPtr<IDSMChapterBag> pCB = m_pMux)
166 pCB->ChapRemoveAll();
167 POSITION pos = m_pTIs.GetHeadPosition();
168 while(pos)
170 if(CTreeItemChapter* t2 = dynamic_cast<CTreeItemChapter*>((CTreeItem*)m_pTIs.GetNext(pos)))
171 pCB->ChapAppend(t2->m_chap.rt, t2->m_chap.name);
175 if(FAILED(m_pMC->Run()))
176 return false;
178 m_tree.EnableWindow(FALSE);
180 return true;
183 void CConvertDlg::AddFilter(HTREEITEM hTIParent, IBaseFilter* pBFParent)
185 BeginEnumPins(pBFParent, pEP, pPin)
187 CComPtr<IPin> pPinTo;
188 CComPtr<IBaseFilter> pBF;
189 if(S_OK != m_pGB->IsPinDirection(pPin, PINDIR_OUTPUT)
190 || FAILED(pPin->ConnectedTo(&pPinTo)) || !pPinTo
191 || !(pBF = GetFilterFromPin(pPinTo)))
192 continue;
194 CTreeItem* t = NULL;
196 if(pBF == m_pMux)
198 t = new CTreeItemPin(pPin, m_tree, hTIParent);
200 else
202 t = new CTreeItemFilter(pBF, m_tree, hTIParent);
203 AddFilter(*t, pBF);
206 EndEnumPins
208 if(CComQIPtr<IDSMPropertyBag> pPB = pBFParent)
210 ULONG props;
211 if(FAILED(pPB->CountProperties(&props)))
212 props = 0;
214 for(ULONG i = 0; i < props; i++)
216 PROPBAG2 PropBag;
217 memset(&PropBag, 0, sizeof(PropBag));
218 ULONG cPropertiesReturned = 0;
219 if(FAILED(pPB->GetPropertyInfo(i, 1, &PropBag, &cPropertiesReturned)))
220 continue;
222 HRESULT hr;
223 CComVariant var;
224 if(SUCCEEDED(pPB->Read(1, &PropBag, NULL, &var, &hr)) && SUCCEEDED(hr))
226 CComQIPtr<IDSMPropertyBag> pPBMux = m_pMux;
227 CComBSTR value;
228 if(pPBMux && FAILED(pPBMux->GetProperty(PropBag.pstrName, &value)))
229 pPBMux->SetProperty(PropBag.pstrName, var.bstrVal);
232 CoTaskMemFree(PropBag.pstrName);
236 CTreeItem* t2 = new CTreeItemResourceFolder(m_tree, hTIParent);
237 if(CComQIPtr<IDSMResourceBag> pRB = pBFParent)
239 for(DWORD i = 0, cnt = pRB->ResGetCount(); i < cnt; i++)
241 CComBSTR name, mime, desc;
242 BYTE* pData = NULL;
243 DWORD len = 0;
244 if(FAILED(pRB->ResGet(i, &name, &desc, &mime, &pData, &len, NULL)))
245 continue;
247 if(len > 0)
249 m_pTIs.AddTail(new CTreeItemResource(CDSMResource(name, desc, mime, pData, len), m_tree, *t2));
252 CoTaskMemFree(pData);
255 m_tree.Expand(*t2, TVE_EXPAND);
257 CTreeItem* t3 = new CTreeItemChapterFolder(m_tree, hTIParent);
258 if(CComQIPtr<IDSMChapterBag> pCB = pBFParent)
260 for(DWORD i = 0, cnt = pCB->ChapGetCount(); i < cnt; i++)
262 REFERENCE_TIME rt;
263 CComBSTR name;
264 if(FAILED(pCB->ChapGet(i, &rt, &name)))
265 continue;
267 m_pTIs.AddTail(new CTreeItemChapter(CDSMChapter(rt, name), m_tree, *t3));
270 m_tree.Expand(*t3, TVE_EXPAND);
272 m_tree.Expand(hTIParent, TVE_EXPAND);
275 void CConvertDlg::DeleteFilter(IBaseFilter* pBF)
277 BeginEnumPins(pBF, pEP, pPin)
279 CComPtr<IPin> pPinTo;
280 CComPtr<IBaseFilter> pBF;
281 if(S_OK != m_pGB->IsPinDirection(pPin, PINDIR_OUTPUT)
282 || FAILED(pPin->ConnectedTo(&pPinTo)) || !pPinTo
283 || !(pBF = GetFilterFromPin(pPinTo)))
284 continue;
286 if(pBF != m_pMux) DeleteFilter(pBF);
288 EndEnumPins
290 m_pGB->RemoveFilter(pBF);
293 void CConvertDlg::DeleteItem(HTREEITEM hTI)
295 if(!hTI) return;
297 DeleteChildren(hTI);
299 CTreeItem* t = (CTreeItem*)m_tree.GetItemData(hTI);
300 if(POSITION pos = m_pTIs.Find(t)) m_pTIs.RemoveAt(pos);
301 delete t;
302 m_tree.DeleteItem(hTI);
305 void CConvertDlg::DeleteChildren(HTREEITEM hTI)
307 if(!hTI) return;
309 if(m_tree.ItemHasChildren(hTI))
311 HTREEITEM hChildItem = m_tree.GetChildItem(hTI);
313 while(hChildItem != NULL)
315 HTREEITEM hNextItem = m_tree.GetNextItem(hChildItem, TVGN_NEXT);
316 DeleteItem(hChildItem);
317 hChildItem = hNextItem;
322 HTREEITEM CConvertDlg::HitTest(CPoint& sp, CPoint& cp)
324 sp = CPoint((LPARAM)GetMessagePos());
325 cp = sp;
326 m_tree.ScreenToClient(&cp);
327 UINT flags = 0;
328 HTREEITEM hTI = m_tree.HitTest(cp, &flags);
329 return hTI && (flags&TVHT_ONITEM) ? hTI : NULL;
332 void CConvertDlg::ShowPopup(CPoint p)
334 CMenu m;
335 m.CreatePopupMenu();
337 int i = 1;
338 m.AppendMenu(MF_STRING, i++, ResStr(IDS_CONVERT_ADDFILE));
339 m.AppendMenu(MF_SEPARATOR);
340 m.AppendMenu(MF_STRING, i++, ResStr(IDS_CONVERT_PROPERTIES));
342 switch((int)m.TrackPopupMenu(TPM_LEFTBUTTON|TPM_RETURNCMD, p.x, p.y, this))
344 case 1:
346 CFileDialog fd(TRUE, NULL, m_fn,
347 OFN_EXPLORER|OFN_ENABLESIZING|OFN_HIDEREADONLY|OFN_NOVALIDATE,
348 _T("Media files|*.*||"), this, 0);
349 if(fd.DoModal() == IDOK) AddFile(fd.GetPathName());
351 break;
352 case 2:
353 EditProperties(CComQIPtr<IDSMPropertyBag>(m_pMux));
354 break;
358 void CConvertDlg::ShowFilePopup(HTREEITEM hTI, CPoint p)
360 CTreeItemFile* t = dynamic_cast<CTreeItemFile*>((CTreeItem*)m_tree.GetItemData(hTI));
361 ASSERT(t);
363 CMenu m;
364 m.CreatePopupMenu();
366 int i = 1;
367 m.AppendMenu(MF_STRING, i++, ResStr(IDS_CONVERT_REMOVE));
369 switch((int)m.TrackPopupMenu(TPM_LEFTBUTTON|TPM_RETURNCMD, p.x, p.y, this))
371 case 1:
372 DeleteFilter(t->m_pBF);
373 DeleteItem(hTI);
374 break;
378 void CConvertDlg::ShowPinPopup(HTREEITEM hTI, CPoint p)
380 CTreeItemPin* t = dynamic_cast<CTreeItemPin*>((CTreeItem*)m_tree.GetItemData(hTI));
381 ASSERT(t);
383 if(!t->m_pPin) return;
385 CComPtr<IPin> pPinTo;
386 t->m_pPin->ConnectedTo(&pPinTo);
388 CMediaType mt;
389 if(pPinTo) t->m_pPin->ConnectionMediaType(&mt);
391 CAtlArray<CMediaType> mts;
392 BeginEnumMediaTypes(t->m_pPin, pEMT, pmt)
393 mts.Add(*pmt);
394 EndEnumMediaTypes(pmt)
396 CMenu m;
397 m.CreatePopupMenu();
399 int i = 1, mtbase = 1000, mti = mtbase;
401 m.AppendMenu(MF_STRING, i++, !pPinTo ? ResStr(IDS_CONVERT_ENABLESTREAM) : ResStr(IDS_CONVERT_DISABLESTREAM));
402 m.AppendMenu(MF_STRING | (!pPinTo ? MF_GRAYED : 0), i++, ResStr(IDS_CONVERT_DEMUXSTREAM));
404 if(mts.GetCount() > 1)
406 m.AppendMenu(MF_SEPARATOR);
407 for(int i = 0; i < mts.GetCount(); i++)
408 m.AppendMenu(MF_STRING | (mts[i] == mt ? MF_CHECKED : 0), mti++, CMediaTypeEx(mts[i]).ToString());
411 m.AppendMenu(MF_SEPARATOR);
412 m.AppendMenu(MF_STRING | (!pPinTo ? MF_GRAYED : 0), i++, ResStr(IDS_CONVERT_PINPROPERTIES));
414 switch(i = (int)m.TrackPopupMenu(TPM_LEFTBUTTON|TPM_RETURNCMD, p.x, p.y, this))
416 case 1:
417 if(pPinTo) {m_pGB->Disconnect(pPinTo); m_pGB->Disconnect(t->m_pPin);}
418 else if(pPinTo = GetFirstDisconnectedPin(m_pMux, PINDIR_INPUT)) m_pGB->ConnectDirect(t->m_pPin, pPinTo, NULL);
419 t->Update();
420 break;
421 case 2:
423 UpdateData();
425 CString ext = _T("raw");
427 if(mt.subtype == MEDIASUBTYPE_AAC) ext = _T("aac");
428 else if(mt.subtype == MEDIASUBTYPE_MP3) ext = _T("mp3");
429 else if(mt.subtype == FOURCCMap(WAVE_FORMAT_MPEG)) ext = _T("m1a");
430 else if(mt.subtype == MEDIASUBTYPE_MPEG2_AUDIO) ext = _T("m2a");
431 else if(mt.subtype == MEDIASUBTYPE_WAVE_DOLBY_AC3 || mt.subtype == MEDIASUBTYPE_DOLBY_AC3) ext = _T("ac3");
432 else if(mt.subtype == MEDIASUBTYPE_WAVE_DTS || mt.subtype == MEDIASUBTYPE_DTS) ext = _T("dts");
433 else if((mt.subtype == FOURCCMap('1CVA') || mt.subtype == FOURCCMap('1cva')) && mt.formattype == FORMAT_MPEG2_VIDEO) ext = _T("h264");
434 else if(mt.subtype == FOURCCMap('GEPJ') || mt.subtype == FOURCCMap('gepj')) ext = _T("jpg");
435 else if(mt.majortype == MEDIATYPE_Video && mt.subtype == MEDIASUBTYPE_MPEG2_VIDEO) ext = _T("m2v");
436 else if(mt.majortype == MEDIATYPE_Video && mt.subtype == MEDIASUBTYPE_MPEG1Payload) ext = _T("m1v");
437 else if(mt.subtype == MEDIASUBTYPE_UTF8 || mt.majortype == MEDIATYPE_Text) ext = _T("srt");
438 else if(mt.subtype == MEDIASUBTYPE_SSA) ext = _T("ssa");
439 else if(mt.subtype == MEDIASUBTYPE_ASS || mt.subtype == MEDIASUBTYPE_ASS2) ext = _T("ass");
440 else if(mt.subtype == MEDIASUBTYPE_SSF) ext = _T("ssf");
441 else if(mt.subtype == MEDIASUBTYPE_VOBSUB) ext = _T("sub");
442 else if(mt.subtype == MEDIASUBTYPE_PCM || mt.subtype == MEDIASUBTYPE_DVD_LPCM_AUDIO || mt.subtype == FOURCCMap(WAVE_FORMAT_EXTENSIBLE) || mt.subtype == FOURCCMap(WAVE_FORMAT_IEEE_FLOAT)) ext = _T("wav");
443 // TODO: else if...
445 CPath path(m_fn);
446 path.RenameExtension('.' + ext);
448 CFileDialog fd(FALSE, NULL, (LPCTSTR)path,
449 OFN_EXPLORER|OFN_ENABLESIZING|OFN_HIDEREADONLY,
450 _T("Media files|*.*||"), this, 0);
451 if(fd.DoModal() == IDOK)
453 if(!ConvertFile(fd.GetPathName(), pPinTo))
455 AfxMessageBox(_T("Failed to start conversion"));
459 break;
460 case 3:
461 EditProperties(CComQIPtr<IDSMPropertyBag>(pPinTo));
462 break;
463 default:
464 i -= mtbase;
465 if(i >= 0 && i < mts.GetCount())
467 if(pPinTo) {m_pGB->Disconnect(pPinTo); m_pGB->Disconnect(t->m_pPin);}
468 else {pPinTo = GetFirstDisconnectedPin(m_pMux, PINDIR_INPUT);}
469 HRESULT hr = m_pGB->ConnectDirect(t->m_pPin, pPinTo, &mts[i]);
470 if(FAILED(hr))
472 AfxMessageBox(_T("Reconnection attempt failed!"));
473 if(mt.majortype != GUID_NULL)
474 hr = m_pGB->ConnectDirect(t->m_pPin, pPinTo, &mt);
476 t->Update();
478 break;
482 void CConvertDlg::ShowResourceFolderPopup(HTREEITEM hTI, CPoint p)
484 CTreeItemResourceFolder* t = dynamic_cast<CTreeItemResourceFolder*>((CTreeItem*)m_tree.GetItemData(hTI));
485 ASSERT(t);
487 CMenu m;
488 m.CreatePopupMenu();
490 int i = 1;
491 m.AppendMenu(MF_STRING, i++, ResStr(IDS_CONVERT_ADDRESOURCE));
492 if(m_tree.ItemHasChildren(*t))
494 m.AppendMenu(MF_SEPARATOR);
495 m.AppendMenu(MF_STRING, i++, ResStr(IDS_CONVERT_REMOVEALL));
498 switch((int)m.TrackPopupMenu(TPM_LEFTBUTTON|TPM_RETURNCMD, p.x, p.y, this))
500 case 1:
502 CFileDialog fd(TRUE, NULL, NULL,
503 OFN_EXPLORER|OFN_ENABLESIZING|OFN_HIDEREADONLY,
504 _T("All files|*.*||"), this, 0);
505 if(fd.DoModal() == IDOK)
507 CString fn = fd.GetPathName();
508 if(FILE* f = _tfopen(fn, _T("rb")))
510 CDSMResource res;
512 CPath path(fn);
513 path.StripPath();
514 res.name = (LPCTSTR)path;
516 CRegKey key;
517 TCHAR mime[256];
518 ULONG len = countof(mime);
519 if(ERROR_SUCCESS == key.Open(HKEY_CLASSES_ROOT, path.GetExtension().MakeLower(), KEY_READ)
520 && ERROR_SUCCESS == key.QueryStringValue(_T("Content Type"), mime, &len))
521 res.mime = mime;
523 CTreeItemResource* t = new CTreeItemResource(res, m_tree, hTI);
524 m_pTIs.AddTail(t);
526 if(EditResource(t))
528 fseek(f, 0, 2);
529 long size = ftell(f);
530 fseek(f, 0, 0);
531 t->m_res.data.SetCount(size);
532 for(BYTE* ptr = t->m_res.data.GetData(),* end = ptr + size;
533 size > 0 && end - ptr >= size && fread(ptr, min(size, 1024), 1, f) > 0;
534 ptr += 1024, size -= 1024);
535 fclose(f);
537 else
539 DeleteItem(*t);
542 else
544 AfxMessageBox(_T("Cannot open file!"));
548 break;
549 case 2:
550 DeleteChildren(hTI);
551 break;
555 void CConvertDlg::ShowResourcePopup(HTREEITEM hTI, CPoint p)
557 CTreeItemResource* t = dynamic_cast<CTreeItemResource*>((CTreeItem*)m_tree.GetItemData(hTI));
558 ASSERT(t);
560 CMenu m;
561 m.CreatePopupMenu();
563 int i = 1;
564 m.AppendMenu(MF_STRING, i++, ResStr(IDS_CONVERT_REMOVE));
565 m.AppendMenu(MF_STRING, i++, ResStr(IDS_CONVERT_SAVEAS));
566 if(AfxGetAppSettings().fEnableWebServer) m.AppendMenu(MF_STRING, 1000, ResStr(IDS_CONVERT_LAUNCHINBROWSER));
567 m.AppendMenu(MF_SEPARATOR);
568 m.AppendMenu(MF_STRING, i++, ResStr(IDS_CONVERT_RESOURCEPROPERTIES));
570 switch((int)m.TrackPopupMenu(TPM_LEFTBUTTON|TPM_RETURNCMD, p.x, p.y, this))
572 case 1:
573 DeleteItem(*t);
574 break;
575 case 2:
577 CFileDialog fd(FALSE, NULL, CString(t->m_res.name),
578 OFN_EXPLORER|OFN_ENABLESIZING|OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,
579 _T("All files|*.*||"), this, 0);
580 if(fd.DoModal() == IDOK)
582 if(FILE* f = _tfopen(fd.GetPathName(), _T("wb")))
584 fwrite(t->m_res.data.GetData(), 1, t->m_res.data.GetCount(), f);
585 fclose(f);
589 break;
590 case 3:
591 EditResource(t);
592 break;
593 case 1000:
595 CString url;
596 url.Format(_T("http://localhost:%d/convres.html?id=%x"), AfxGetAppSettings().nWebServerPort, (DWORD)&t->m_res);
597 ShellExecute(NULL, _T("open"), url, NULL, NULL, SW_SHOWDEFAULT);
599 break;
603 bool CConvertDlg::EditProperties(IDSMPropertyBag* pPB)
605 CConvertPropsDlg dlg(!!CComQIPtr<IPin>(pPB), this);
607 ULONG props;
608 if(FAILED(pPB->CountProperties(&props)))
609 props = 0;
611 for(ULONG i = 0; i < props; i++)
613 PROPBAG2 PropBag;
614 memset(&PropBag, 0, sizeof(PropBag));
615 ULONG cPropertiesReturned = 0;
616 if(FAILED(pPB->GetPropertyInfo(i, 1, &PropBag, &cPropertiesReturned)))
617 continue;
619 HRESULT hr;
620 CComVariant var;
621 if(SUCCEEDED(pPB->Read(1, &PropBag, NULL, &var, &hr)) && SUCCEEDED(hr))
622 dlg.m_props[CString(PropBag.pstrName)] = CString(var);
624 CoTaskMemFree(PropBag.pstrName);
627 if(IDOK != dlg.DoModal())
628 return false;
630 pPB->DelAllProperties();
632 POSITION pos = dlg.m_props.GetStartPosition();
633 while(pos)
635 CString key, value;
636 dlg.m_props.GetNextAssoc(pos, key, value);
637 pPB->SetProperty(CStringW(key), CStringW(value));
640 return true;
643 bool CConvertDlg::EditResource(CTreeItemResource* t)
645 CConvertResDlg dlg(this);
647 dlg.m_name = t->m_res.name;
648 dlg.m_mime = t->m_res.mime;
649 dlg.m_desc = t->m_res.desc;
651 if(IDOK != dlg.DoModal())
652 return false;
654 t->m_res.name = dlg.m_name;
655 t->m_res.mime = dlg.m_mime;
656 t->m_res.desc = dlg.m_desc;
658 t->Update();
660 return true;
663 void CConvertDlg::ShowChapterFolderPopup(HTREEITEM hTI, CPoint p)
665 CTreeItemChapterFolder* t = dynamic_cast<CTreeItemChapterFolder*>((CTreeItem*)m_tree.GetItemData(hTI));
666 ASSERT(t);
668 CMenu m;
669 m.CreatePopupMenu();
671 int i = 1;
672 m.AppendMenu(MF_STRING, i++, ResStr(IDS_CONVERT_ADDCHAPTER));
673 if(m_tree.ItemHasChildren(*t))
675 m.AppendMenu(MF_SEPARATOR);
676 m.AppendMenu(MF_STRING, i++, ResStr(IDS_CONVERT_REMOVEALL));
679 switch((int)m.TrackPopupMenu(TPM_LEFTBUTTON|TPM_RETURNCMD, p.x, p.y, this))
681 case 1:
683 CDSMChapter chap;
684 CTreeItemChapter* t = new CTreeItemChapter(CDSMChapter(0, L""), m_tree, hTI);
685 m_pTIs.AddTail(t);
686 if(!EditChapter(t))
687 DeleteItem(*t);
689 break;
690 case 2:
691 DeleteChildren(hTI);
692 break;
696 void CConvertDlg::ShowChapterPopup(HTREEITEM hTI, CPoint p)
698 CTreeItemChapter* t = dynamic_cast<CTreeItemChapter*>((CTreeItem*)m_tree.GetItemData(hTI));
699 ASSERT(t);
701 CMenu m;
702 m.CreatePopupMenu();
704 int i = 1;
705 m.AppendMenu(MF_STRING, i++, ResStr(IDS_CONVERT_REMOVE));
706 m.AppendMenu(MF_SEPARATOR);
707 m.AppendMenu(MF_STRING, i++, ResStr(IDS_CONVERT_CHAPTERPROPERTIES));
709 switch((int)m.TrackPopupMenu(TPM_LEFTBUTTON|TPM_RETURNCMD, p.x, p.y, this))
711 case 1:
712 DeleteItem(hTI);
713 break;
714 case 2:
715 EditChapter(t);
716 break;
720 bool CConvertDlg::EditChapter(CTreeItemChapter* t)
722 CConvertChapDlg dlg(this);
724 int h = (int)(t->m_chap.rt/10000000/60/60);
725 int m = (int)(t->m_chap.rt/10000000/60%60);
726 int s = (int)(t->m_chap.rt/10000000%60);
727 int ms = (int)(t->m_chap.rt/10000%1000);
729 dlg.m_name = t->m_chap.name;
730 dlg.m_time.Format(_T("%02d:%02d:%02d.%03d"), h, m, s, ms);
732 if(IDOK != dlg.DoModal())
733 return false;
735 TCHAR c;
736 if(_stscanf(dlg.m_time, _T("%d%c%d%c%d%c%d"), &h, &c, &m, &c, &s, &c, &ms) != 7)
737 return false;
739 t->m_chap.name = dlg.m_name;
740 t->m_chap.rt = ((((__int64)h*60+m)*60+s)*1000+ms)*10000;
742 t->Update();
744 return true;
747 void CConvertDlg::DoDataExchange(CDataExchange* pDX)
749 __super::DoDataExchange(pDX);
750 DDX_Control(pDX, IDC_TREE1, m_tree);
751 DDX_Text(pDX, IDC_EDIT1, m_fn);
754 BOOL CConvertDlg::PreTranslateMessage(MSG* pMsg)
756 if(pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_ESCAPE)
757 return TRUE;
759 return __super::PreTranslateMessage(pMsg);
762 BOOL CConvertDlg::OnInitDialog()
764 __super::OnInitDialog();
766 SetIcon(AfxGetApp()->LoadIcon(IDR_MAINFRAME), TRUE);
767 SetIcon(AfxGetApp()->LoadIcon(IDR_MAINFRAME), FALSE);
769 AddAnchor(IDC_TREE1, TOP_LEFT, BOTTOM_RIGHT);
770 AddAnchor(IDC_EDIT1, BOTTOM_LEFT, BOTTOM_RIGHT);
771 AddAnchor(IDC_BUTTON1, BOTTOM_RIGHT);
772 AddAnchor(IDC_HLINE, BOTTOM_LEFT, BOTTOM_RIGHT);
773 AddAnchor(IDC_BUTTON2, BOTTOM_CENTER);
774 AddAnchor(IDC_BUTTON3, BOTTOM_CENTER);
775 AddAnchor(IDC_BUTTON4, BOTTOM_CENTER);
777 CSize s(400, 200);
778 SetMinTrackSize(s);
780 m_streamtypesbm.LoadBitmap(IDB_STREAMTYPES);
781 m_streamtypes.Create(16, 18, ILC_MASK|ILC_COLOR32, 0, 4);
782 m_streamtypes.Add(&m_streamtypesbm, 0xffffff);
783 m_tree.SetImageList(&m_streamtypes, TVSIL_NORMAL);
785 GetWindowText(m_title);
786 m_nIDEventStatus = SetTimer(1, 1000, NULL);
788 HRESULT hr;
789 m_pMux = new CDSMMuxerFilter(NULL, &hr, false, false);
791 m_pGB = new CFGManagerMuxer(_T("CFGManagerMuxer"), NULL);
792 m_pGB->AddToROT();
794 if(FAILED(m_pGB->AddFilter(m_pMux, L"Mux"))
795 || !(m_pMC = m_pGB) || !(m_pME = m_pGB) || !(m_pMS = m_pMux)
796 || FAILED(m_pME->SetNotifyWindow((OAHWND)m_hWnd, WM_GRAPHNOTIFY, 0)))
798 MessageBeep(-1);
799 SendMessage(WM_CLOSE);
800 return TRUE;
803 return TRUE; // return TRUE unless you set the focus to a control
804 // EXCEPTION: OCX Property Pages should return FALSE
807 void CConvertDlg::OnOK()
811 BEGIN_MESSAGE_MAP(CConvertDlg, CResizableDialog)
812 ON_MESSAGE(WM_GRAPHNOTIFY, OnGraphNotify)
813 ON_WM_DROPFILES()
814 ON_WM_CLOSE()
815 ON_NOTIFY(NM_CLICK, IDC_TREE1, OnNMClickTree1)
816 ON_NOTIFY(NM_RCLICK, IDC_TREE1, OnNMRclickTree1)
817 ON_NOTIFY(NM_DBLCLK, IDC_TREE1, OnNMDblclkTree1)
818 ON_BN_CLICKED(IDC_BUTTON1, OnBnClickedButton1)
819 ON_UPDATE_COMMAND_UI(IDC_BUTTON1, OnUpdateButton1)
820 ON_WM_TIMER()
821 ON_BN_CLICKED(IDC_BUTTON2, OnBnClickedButton2)
822 ON_UPDATE_COMMAND_UI(IDC_BUTTON2, OnUpdateButton2)
823 ON_BN_CLICKED(IDC_BUTTON3, OnBnClickedButton3)
824 ON_UPDATE_COMMAND_UI(IDC_BUTTON3, OnUpdateButton3)
825 ON_BN_CLICKED(IDC_BUTTON4, OnBnClickedButton4)
826 ON_UPDATE_COMMAND_UI(IDC_BUTTON4, OnUpdateButton4)
827 END_MESSAGE_MAP()
829 // CConvertDlg message handlers
831 LRESULT CConvertDlg::OnGraphNotify(WPARAM wParam, LPARAM lParam)
833 HRESULT hr = S_OK;
835 LONG evCode, evParam1, evParam2;
836 while(m_pME && SUCCEEDED(m_pME->GetEvent(&evCode, (LONG_PTR*)&evParam1, (LONG_PTR*)&evParam2, 0)))
838 hr = m_pME->FreeEventParams(evCode, evParam1, evParam2);
840 bool fStop = false;
842 if(EC_COMPLETE == evCode)
844 fStop = true;
846 else if(EC_ERRORABORT == evCode)
848 fStop = true;
850 CString errmsg;
851 LPVOID lpMsgBuf;
852 if(FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
853 NULL, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL))
855 errmsg = (LPCTSTR)lpMsgBuf;
856 LocalFree(lpMsgBuf);
859 CString str;
860 str.Format(_T("Could not complete conversion, the output file is most likely unusable.\n\nError code: 0x%08x"), evParam1);
861 if(!errmsg.IsEmpty()) str += _T(" (") + errmsg + _T(")");
862 AfxMessageBox(str, MB_OK);
865 if(fStop && m_pMC)
867 m_pMC->Stop();
868 m_tree.EnableWindow(TRUE);
872 return hr;
875 void CConvertDlg::OnDropFiles(HDROP hDropInfo)
877 for(int i = 0, j = DragQueryFile(hDropInfo, 0xffffffff, 0, 0); i < j; i++)
879 CString fn;
880 fn.ReleaseBufferSetLength(DragQueryFile(hDropInfo, i, fn.GetBuffer(MAX_PATH), MAX_PATH));
882 AddFile(fn);
885 __super::OnDropFiles(hDropInfo);
888 void CConvertDlg::OnClose()
890 HTREEITEM hTI = m_tree.GetRootItem();
891 while(hTI)
893 HTREEITEM hTINext = m_tree.GetNextSiblingItem(hTI);
894 DeleteItem(hTI);
895 hTI = hTINext;
898 m_pGB->RemoveFromROT();
899 m_pGB = NULL;
901 __super::OnClose();
904 void CConvertDlg::OnNMClickTree1(NMHDR* pNMHDR, LRESULT* pResult)
906 CPoint sp, cp;
907 HTREEITEM hTI = HitTest(sp, cp);
908 if(!hTI) return;
909 m_tree.SelectItem(hTI);
911 *pResult = 0;
914 void CConvertDlg::OnNMRclickTree1(NMHDR* pNMHDR, LRESULT* pResult)
916 CPoint sp, cp;
917 HTREEITEM hTI = HitTest(sp, cp);
919 if(hTI)
921 m_tree.SelectItem(hTI);
923 CTreeItem* t = (CTreeItem*)m_tree.GetItemData(hTI);
925 if(dynamic_cast<CTreeItemPin*>(t))
926 ShowPinPopup(hTI, sp);
927 else if(dynamic_cast<CTreeItemFile*>(t))
928 ShowFilePopup(hTI, sp);
929 else if(dynamic_cast<CTreeItemResourceFolder*>(t))
930 ShowResourceFolderPopup(hTI, sp);
931 else if(dynamic_cast<CTreeItemResource*>(t))
932 ShowResourcePopup(hTI, sp);
933 else if(dynamic_cast<CTreeItemChapterFolder*>(t))
934 ShowChapterFolderPopup(hTI, sp);
935 else if(dynamic_cast<CTreeItemChapter*>(t))
936 ShowChapterPopup(hTI, sp);
938 else
940 ShowPopup(sp);
943 *pResult = 0;
946 void CConvertDlg::OnNMDblclkTree1(NMHDR *pNMHDR, LRESULT *pResult)
948 CPoint sp, cp;
949 HTREEITEM hTI = HitTest(sp, cp);
951 if(hTI)
953 CTreeItem* t = (CTreeItem*)m_tree.GetItemData(hTI);
955 if(CTreeItemPin* t2 = dynamic_cast<CTreeItemPin*>(t))
957 CComPtr<IPin> pPinTo;
958 t2->m_pPin->ConnectedTo(&pPinTo);
960 if(CComQIPtr<IDSMPropertyBag> pPB = pPinTo)
961 EditProperties(pPB);
963 else if(CTreeItemResource* t2 = dynamic_cast<CTreeItemResource*>(t))
965 EditResource(t2);
967 else if(CTreeItemChapter* t2 = dynamic_cast<CTreeItemChapter*>(t))
969 EditChapter(t2);
973 *pResult = 0;
976 void CConvertDlg::OnBnClickedButton1()
978 UpdateData();
980 CFileDialog fd(FALSE, _T(".dsm"), m_fn,
981 OFN_EXPLORER|OFN_ENABLESIZING|OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,
982 _T("DirectShow Media file|*.dsm|All files|*.*|"), this, 0);
984 if(fd.DoModal() == IDOK)
986 m_fn = fd.GetPathName();
987 UpdateData(FALSE);
991 void CConvertDlg::OnUpdateButton1(CCmdUI* pCmdUI)
993 OAFilterState fs;
994 pCmdUI->Enable(m_pMC && SUCCEEDED(m_pMC->GetState(0, &fs)) && fs == State_Stopped);
997 void CConvertDlg::OnTimer(UINT nIDEvent)
999 if(nIDEvent == m_nIDEventStatus && m_pMS && m_pMC)
1001 OAFilterState fs;
1002 if(SUCCEEDED(m_pMC->GetState(0, &fs)) && fs != State_Stopped)
1004 GUID tf;
1005 m_pMS->GetTimeFormat(&tf);
1007 REFERENCE_TIME rtCur, rtDur;
1008 HRESULT hr = m_pMS->GetDuration(&rtDur);
1009 m_pMS->GetCurrentPosition(&rtCur);
1011 CString str;
1012 if(hr == S_OK && rtDur != 0) str.Format(_T("%.2f%%"), 1.0 * (rtCur * 100) / rtDur);
1013 else if(hr == S_OK && rtDur == 0) str = _T("Live");
1014 else if(tf == TIME_FORMAT_BYTE) str.Format(_T("%.2fKB"), 1.0 * rtCur / 1024);
1015 else if(tf == TIME_FORMAT_MEDIA_TIME) str.Format(_T("%02d:%02d:%02d"), int(rtCur/3600000000)%60, int(rtCur/60000000)%60, int(rtCur/1000000)%60);
1016 else str = _T("Please Wait");
1018 SetWindowText(_T("Converting - ") + str);
1020 else
1022 SetWindowText(m_title);
1026 __super::OnTimer(nIDEvent);
1029 void CConvertDlg::OnBnClickedButton2()
1031 OAFilterState fs;
1032 if(FAILED(m_pMC->GetState(0, &fs)))
1033 return;
1035 if(fs != State_Stopped)
1037 m_pMC->Run();
1038 return;
1041 UpdateData();
1043 if(!ConvertFile(m_fn))
1045 AfxMessageBox(_T("Failed to start conversion"));
1049 void CConvertDlg::OnUpdateButton2(CCmdUI* pCmdUI)
1051 int nIn, nOut, nInC, nOutC;
1052 CountPins(m_pMux, nIn, nOut, nInC, nOutC);
1054 OAFilterState fs;
1055 pCmdUI->Enable(nInC > 0 && GetDlgItem(IDC_EDIT1)->GetWindowTextLength() > 0
1056 && m_pMS && m_pMC && SUCCEEDED(m_pMC->GetState(0, &fs)) && fs != State_Running);
1059 void CConvertDlg::OnBnClickedButton3()
1061 if(m_pMC) m_pMC->Pause();
1064 void CConvertDlg::OnUpdateButton3(CCmdUI* pCmdUI)
1066 OAFilterState fs;
1067 pCmdUI->Enable(m_pMC && SUCCEEDED(m_pMC->GetState(0, &fs)) && fs == State_Running);
1070 void CConvertDlg::OnBnClickedButton4()
1072 if(m_pMC) m_pMC->Stop();
1073 m_tree.EnableWindow(TRUE);
1076 void CConvertDlg::OnUpdateButton4(CCmdUI* pCmdUI)
1078 OAFilterState fs;
1079 pCmdUI->Enable(m_pMC && SUCCEEDED(m_pMC->GetState(0, &fs)) && fs != State_Stopped);
1083 // CFilterTreeCtrl
1086 CFilterTreeCtrl::CFilterTreeCtrl()
1090 void CFilterTreeCtrl::PreSubclassWindow()
1092 EnableToolTips(TRUE);
1094 __super::PreSubclassWindow();
1097 INT_PTR CFilterTreeCtrl::OnToolHitTest(CPoint p, TOOLINFO* pTI) const
1099 UINT nFlags;
1100 HTREEITEM hTI = HitTest(p, &nFlags);
1101 if(nFlags & TVHT_ONITEM)
1103 CRect r;
1104 GetItemRect(hTI, r, TRUE);
1105 pTI->hwnd = m_hWnd;
1106 pTI->uId = (UINT)hTI;
1107 pTI->lpszText = LPSTR_TEXTCALLBACK;
1108 pTI->rect = r;
1109 return pTI->uId;
1112 return -1;
1115 BEGIN_MESSAGE_MAP(CFilterTreeCtrl, CTreeCtrl)
1116 ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText)
1117 ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipText)
1118 END_MESSAGE_MAP()
1120 BOOL CFilterTreeCtrl::OnToolTipText(UINT id, NMHDR* pNMHDR, LRESULT* pResult)
1122 TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
1123 TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
1125 UINT nID = pNMHDR->idFrom;
1127 if(nID == (UINT)m_hWnd
1128 && (pNMHDR->code == TTN_NEEDTEXTA && (pTTTA->uFlags & TTF_IDISHWND)
1129 || pNMHDR->code == TTN_NEEDTEXTW && (pTTTW->uFlags & TTF_IDISHWND)))
1130 return FALSE;
1132 ::SendMessage(pNMHDR->hwndFrom, TTM_SETMAXTIPWIDTH, 0, (LPARAM)(INT)1000);
1134 HTREEITEM hTI = (HTREEITEM)nID;
1136 CString str;
1137 static CStringA m_strTipTextA;
1138 static CStringW m_strTipTextW;
1140 CConvertDlg::CTreeItem* t = (CConvertDlg::CTreeItem*)GetItemData(hTI);
1141 if(!t || !t->ToolTip(str)) return FALSE;
1143 m_strTipTextA = str;
1144 m_strTipTextW = str;
1146 if(pNMHDR->code == TTN_NEEDTEXTA) pTTTA->lpszText = (LPSTR)(LPCSTR)m_strTipTextA;
1147 else pTTTW->lpszText = (LPWSTR)(LPCWSTR)m_strTipTextW;
1149 *pResult = 0;
1151 return TRUE; // message was handled
1155 // CConvertDlg::CTreeItem*
1158 CConvertDlg::CTreeItem::CTreeItem(CTreeCtrl& tree, HTREEITEM hTIParent)
1159 : m_tree(tree)
1161 m_hTI = m_tree.InsertItem(_T(""), hTIParent);
1162 m_tree.SetItemData(m_hTI, (DWORD_PTR)this);
1163 Update();
1166 CConvertDlg::CTreeItem::~CTreeItem()
1170 void CConvertDlg::CTreeItem::SetLabel(LPCTSTR label)
1172 m_tree.SetItemText(m_hTI, label);
1175 void CConvertDlg::CTreeItem::SetImage(int nImage, int nSelectedImage)
1177 m_tree.SetItemImage(m_hTI, nImage, nSelectedImage);
1182 CConvertDlg::CTreeItemFilter::CTreeItemFilter(IBaseFilter* pBF, CTreeCtrl& tree, HTREEITEM hTIParent)
1183 : CTreeItem(tree, hTIParent)
1184 , m_pBF(pBF)
1186 Update();
1189 void CConvertDlg::CTreeItemFilter::Update()
1191 SetLabel(CString(GetFilterName(m_pBF)));
1196 CConvertDlg::CTreeItemFile::CTreeItemFile(CString fn, IBaseFilter* pBF, CTreeCtrl& tree, HTREEITEM hTIParent)
1197 : CTreeItemFilter(pBF, tree, hTIParent)
1198 , m_fn(fn)
1200 Update();
1203 void CConvertDlg::CTreeItemFile::Update()
1205 CPath path = m_fn;
1206 path.StripPath();
1207 SetLabel(path);
1210 bool CConvertDlg::CTreeItemFile::ToolTip(CString& str)
1212 str = m_fn;
1213 return true;
1218 CConvertDlg::CTreeItemPin::CTreeItemPin(IPin* pPin, CTreeCtrl& tree, HTREEITEM hTIParent)
1219 : CTreeItem(tree, hTIParent)
1220 , m_pPin(pPin)
1222 Update();
1225 void CConvertDlg::CTreeItemPin::Update()
1227 if(!m_pPin) {ASSERT(0); return;}
1229 CString label = GetPinName(m_pPin);
1230 if(!IsConnected()) label = _T("[D] ") + label;
1231 SetLabel(label);
1233 CMediaType mt;
1234 if(S_OK == m_pPin->ConnectionMediaType(&mt))
1236 if(mt.majortype == MEDIATYPE_Video) SetImage(1, 1);
1237 else if(mt.majortype == MEDIATYPE_Audio) SetImage(2, 2);
1238 else if(mt.majortype == MEDIATYPE_Text || mt.majortype == MEDIATYPE_Subtitle) SetImage(3, 3);
1242 bool CConvertDlg::CTreeItemPin::ToolTip(CString& str)
1244 CMediaTypeEx mt;
1245 if(FAILED(m_pPin->ConnectionMediaType(&mt))) return false;
1246 str = mt.ToString(m_pPin);
1247 return true;
1250 bool CConvertDlg::CTreeItemPin::IsConnected()
1252 CComPtr<IPin> pPinTo;
1253 return m_pPin && SUCCEEDED(m_pPin->ConnectedTo(&pPinTo)) && pPinTo;
1258 CConvertDlg::CTreeItemResourceFolder::CTreeItemResourceFolder(CTreeCtrl& tree, HTREEITEM hTIParent)
1259 : CTreeItem(tree, hTIParent)
1261 Update();
1264 void CConvertDlg::CTreeItemResourceFolder::Update()
1266 SetLabel(_T("Resources"));
1269 bool CConvertDlg::CTreeItemResourceFolder::ToolTip(CString& str)
1271 if(!m_tree.ItemHasChildren(m_hTI))
1272 return false;
1274 int files = 0;
1275 float size = 0;
1277 HTREEITEM hChildItem = m_tree.GetChildItem(m_hTI);
1279 while(hChildItem != NULL)
1281 HTREEITEM hNextItem = m_tree.GetNextItem(hChildItem, TVGN_NEXT);
1282 if(CTreeItemResource* t = dynamic_cast<CTreeItemResource*>((CTreeItem*)m_tree.GetItemData(hChildItem)))
1283 size += t->m_res.data.GetCount(), files++;
1284 hChildItem = hNextItem;
1287 size /= 1024;
1288 if(size < 1024) str.Format(_T("%d file(s), %.2f KB"), files, size);
1289 else str.Format(_T("%d file(s), %.2f MB"), files, size/1024);
1291 return true;
1296 CConvertDlg::CTreeItemResource::CTreeItemResource(const CDSMResource& res, CTreeCtrl& tree, HTREEITEM hTIParent)
1297 : CTreeItem(tree, hTIParent)
1299 m_res = res;
1300 Update();
1303 CConvertDlg::CTreeItemResource::~CTreeItemResource()
1307 void CConvertDlg::CTreeItemResource::Update()
1309 SetLabel(CString(m_res.name));
1311 CStringW mime = m_res.mime;
1312 mime.Trim();
1313 mime.MakeLower();
1314 if(mime == L"application/x-truetype-font") SetImage(4, 4);
1315 else if(mime.Find(L"text/") == 0) SetImage(5, 5);
1316 else SetImage(6, 6);
1319 bool CConvertDlg::CTreeItemResource::ToolTip(CString& str)
1321 if(!m_res.mime.IsEmpty()) str = CString(m_res.mime) + _T("\r\n\r\n");
1322 if(!m_res.desc.IsEmpty()) str += CString(m_res.desc);
1323 str.Trim();
1324 return true;
1329 CConvertDlg::CTreeItemChapterFolder::CTreeItemChapterFolder(CTreeCtrl& tree, HTREEITEM hTIParent)
1330 : CTreeItem(tree, hTIParent)
1332 Update();
1335 void CConvertDlg::CTreeItemChapterFolder::Update()
1337 SetLabel(_T("Chapters"));
1342 CConvertDlg::CTreeItemChapter::CTreeItemChapter(const CDSMChapter& chap, CTreeCtrl& tree, HTREEITEM hTIParent)
1343 : CTreeItem(tree, hTIParent)
1345 m_chap = chap;
1346 Update();
1349 void CConvertDlg::CTreeItemChapter::Update()
1351 REFERENCE_TIME rt = m_chap.rt;
1352 rt /= 10000;
1353 int ms = (int)(rt%1000);
1354 rt /= 1000;
1355 int s = (int)(rt%60);
1356 rt /= 60;
1357 int m = (int)(rt%60);
1358 rt /= 60;
1359 int h = (int)(rt);
1361 CString label;
1362 label.Format(_T("%02d:%02d:%02d.%03d - %s"), h, m, s, ms, CString(m_chap.name));
1363 SetLabel(label);
1365 SetImage(7, 7);