/* * $Id$ * * (C) 2003-2006 Gabest * (C) 2006-2010 see AUTHORS * * This file is part of mplayerc. * * Mplayerc is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * Mplayerc is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include "stdafx.h" #include #include "mplayerc.h" #include "../../filters/filters.h" #include #include "FGManager.h" #include "ConvertPropsDlg.h" #include "ConvertResDlg.h" #include "ConvertChapDlg.h" #include "ConvertDlg.h" // TODO: subtitle source filter for vobsub // CConvertDlg dialog CConvertDlg::CConvertDlg(CWnd* pParent /*=NULL*/) : CResizableDialog(CConvertDlg::IDD, pParent) , m_fn(_T("")) { } CConvertDlg::~CConvertDlg() { } void CConvertDlg::AddFile(CString fn) { CString protocol; int i = fn.Find(_T("://")); if(i > 0) { CString url = fn.Mid(i); CPath path(fn.Left(i)); path.StripPath(); protocol = (LPCTSTR)path; fn = (LPCTSTR)path + url; } CComPtr pBF; if(FAILED(m_pGB->AddSourceFilter(CStringW(fn), CStringW(fn), &pBF))) return; int nConnected = 0; BeginEnumPins(pBF, pEP, pPin) if(S_OK == m_pGB->ConnectFilter(pPin, m_pMux)) nConnected++; EndEnumPins; if(!nConnected) { MessageBeep((UINT)-1); DeleteFilter(pBF); return; } if(m_tree.GetCount() == 0) { if(CComQIPtr pPB = m_pMux) pPB->DelAllProperties(); CString ext(_T(".dsm")); if(!protocol.IsEmpty()) { m_fn = protocol + ext; } else { CPath p(fn); if(ext.CompareNoCase(p.GetExtension()) == 0) ext = _T(" (remuxed)") + ext; p.RemoveExtension(); m_fn = (LPCTSTR)p + ext; } UpdateData(FALSE); } CTreeItemFile* t = DNew CTreeItemFile(fn, pBF, m_tree, NULL); AddFilter(*t, pBF); m_tree.Expand(*t, TVE_EXPAND); m_tree.EnsureVisible(*t); } bool CConvertDlg::ConvertFile(LPCTSTR fn, IPin* pPin) { OAFilterState fs; if(!m_pMC || FAILED(m_pMC->GetState(0, &fs)) || fs != State_Stopped) return false; m_pGB->NukeDownstream(m_pMux); CComPtr pFW; pFW.CoCreateInstance(CLSID_FileWriter); CComQIPtr pFSF = pFW; if(pPin) { CComQIPtr pRP = pPin; if(!pRP) return false; pPin = pRP->GetRelatedPin(); } else { pPin = GetFirstPin(m_pMux, PINDIR_OUTPUT); } if(!pPin || !pFSF || FAILED(m_pGB->AddFilter(pFW, NULL)) || FAILED(pFSF->SetFileName(CStringW(fn), NULL)) || FAILED(pFSF->SetMode(AM_FILE_OVERWRITE)) || FAILED(m_pGB->ConnectDirect(pPin, GetFirstPin(pFW), NULL))) { m_pGB->RemoveFilter(pFW); return false; } if(m_pMS) { LONGLONG pos = 0; m_pMS->SetPositions(&pos, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning); } if(CComQIPtr pPB = m_pMux) { pPB->SetProperty(L"APPL", L"Media Player Classic"); } if(CComQIPtr pRB = m_pMux) { pRB->ResRemoveAll(0); POSITION pos = m_pTIs.GetHeadPosition(); while(pos) { if(CTreeItemResource* t2 = dynamic_cast((CTreeItem*)m_pTIs.GetNext(pos))) pRB->ResAppend( t2->m_res.name, t2->m_res.desc, t2->m_res.mime, t2->m_res.data.GetData(), t2->m_res.data.GetCount(), NULL); } } if(CComQIPtr pCB = m_pMux) { pCB->ChapRemoveAll(); POSITION pos = m_pTIs.GetHeadPosition(); while(pos) { if(CTreeItemChapter* t2 = dynamic_cast((CTreeItem*)m_pTIs.GetNext(pos))) pCB->ChapAppend(t2->m_chap.rt, t2->m_chap.name); } } if(FAILED(m_pMC->Run())) return false; m_tree.EnableWindow(FALSE); return true; } void CConvertDlg::AddFilter(HTREEITEM hTIParent, IBaseFilter* pBFParent) { BeginEnumPins(pBFParent, pEP, pPin) { CComPtr pPinTo; CComPtr pBF; if(S_OK != m_pGB->IsPinDirection(pPin, PINDIR_OUTPUT) || FAILED(pPin->ConnectedTo(&pPinTo)) || !pPinTo || !(pBF = GetFilterFromPin(pPinTo))) continue; CTreeItem* t = NULL; if(pBF == m_pMux) { t = DNew CTreeItemPin(pPin, m_tree, hTIParent); } else { t = DNew CTreeItemFilter(pBF, m_tree, hTIParent); AddFilter(*t, pBF); } } EndEnumPins; if(CComQIPtr pPB = pBFParent) { ULONG props; if(FAILED(pPB->CountProperties(&props))) props = 0; for(ULONG i = 0; i < props; i++) { PROPBAG2 PropBag; memset(&PropBag, 0, sizeof(PropBag)); ULONG cPropertiesReturned = 0; if(FAILED(pPB->GetPropertyInfo(i, 1, &PropBag, &cPropertiesReturned))) continue; HRESULT hr; CComVariant var; if(SUCCEEDED(pPB->Read(1, &PropBag, NULL, &var, &hr)) && SUCCEEDED(hr)) { CComQIPtr pPBMux = m_pMux; CComBSTR value; if(pPBMux && FAILED(pPBMux->GetProperty(PropBag.pstrName, &value))) pPBMux->SetProperty(PropBag.pstrName, var.bstrVal); } CoTaskMemFree(PropBag.pstrName); } } CTreeItem* t2 = DNew CTreeItemResourceFolder(m_tree, hTIParent); if(CComQIPtr pRB = pBFParent) { for(DWORD i = 0, cnt = pRB->ResGetCount(); i < cnt; i++) { CComBSTR name, mime, desc; BYTE* pData = NULL; DWORD len = 0; if(FAILED(pRB->ResGet(i, &name, &desc, &mime, &pData, &len, NULL))) continue; if(len > 0) { m_pTIs.AddTail(DNew CTreeItemResource(CDSMResource(name, desc, mime, pData, len), m_tree, *t2)); } CoTaskMemFree(pData); } } m_tree.Expand(*t2, TVE_EXPAND); CTreeItem* t3 = DNew CTreeItemChapterFolder(m_tree, hTIParent); if(CComQIPtr pCB = pBFParent) { for(DWORD i = 0, cnt = pCB->ChapGetCount(); i < cnt; i++) { REFERENCE_TIME rt; CComBSTR name; if(FAILED(pCB->ChapGet(i, &rt, &name))) continue; m_pTIs.AddTail(DNew CTreeItemChapter(CDSMChapter(rt, name), m_tree, *t3)); } } m_tree.Expand(*t3, TVE_EXPAND); m_tree.Expand(hTIParent, TVE_EXPAND); } void CConvertDlg::DeleteFilter(IBaseFilter* pBF) { BeginEnumPins(pBF, pEP, pPin) { CComPtr pPinTo; CComPtr pBF; if(S_OK != m_pGB->IsPinDirection(pPin, PINDIR_OUTPUT) || FAILED(pPin->ConnectedTo(&pPinTo)) || !pPinTo || !(pBF = GetFilterFromPin(pPinTo))) continue; if(pBF != m_pMux) DeleteFilter(pBF); } EndEnumPins; m_pGB->RemoveFilter(pBF); } void CConvertDlg::DeleteItem(HTREEITEM hTI) { if(!hTI) return; DeleteChildren(hTI); CTreeItem* t = (CTreeItem*)m_tree.GetItemData(hTI); if(POSITION pos = m_pTIs.Find(t)) m_pTIs.RemoveAt(pos); delete t; m_tree.DeleteItem(hTI); } void CConvertDlg::DeleteChildren(HTREEITEM hTI) { if(!hTI) return; if(m_tree.ItemHasChildren(hTI)) { HTREEITEM hChildItem = m_tree.GetChildItem(hTI); while(hChildItem != NULL) { HTREEITEM hNextItem = m_tree.GetNextItem(hChildItem, TVGN_NEXT); DeleteItem(hChildItem); hChildItem = hNextItem; } } } HTREEITEM CConvertDlg::HitTest(CPoint& sp, CPoint& cp) { sp = CPoint((LPARAM)GetMessagePos()); cp = sp; m_tree.ScreenToClient(&cp); UINT flags = 0; HTREEITEM hTI = m_tree.HitTest(cp, &flags); return hTI && (flags&TVHT_ONITEM) ? hTI : NULL; } void CConvertDlg::ShowPopup(CPoint p) { CMenu m; m.CreatePopupMenu(); int i = 1; m.AppendMenu(MF_STRING, i++, ResStr(IDS_CONVERT_ADDFILE)); m.AppendMenu(MF_SEPARATOR); m.AppendMenu(MF_STRING, i++, ResStr(IDS_CONVERT_PROPERTIES)); switch((int)m.TrackPopupMenu(TPM_LEFTBUTTON|TPM_RETURNCMD, p.x, p.y, this)) { case 1: { CFileDialog fd(TRUE, NULL, m_fn, OFN_EXPLORER|OFN_ENABLESIZING|OFN_HIDEREADONLY|OFN_NOVALIDATE, ResStr(IDS_CONVERTDLG_0), this, 0); if(fd.DoModal() == IDOK) AddFile(fd.GetPathName()); } break; case 2: EditProperties(CComQIPtr(m_pMux)); break; } } void CConvertDlg::ShowFilePopup(HTREEITEM hTI, CPoint p) { CTreeItemFile* t = dynamic_cast((CTreeItem*)m_tree.GetItemData(hTI)); ASSERT(t); CMenu m; m.CreatePopupMenu(); int i = 1; m.AppendMenu(MF_STRING, i++, ResStr(IDS_CONVERT_REMOVE)); switch((int)m.TrackPopupMenu(TPM_LEFTBUTTON|TPM_RETURNCMD, p.x, p.y, this)) { case 1: DeleteFilter(t->m_pBF); DeleteItem(hTI); break; } } void CConvertDlg::ShowPinPopup(HTREEITEM hTI, CPoint p) { CTreeItemPin* t = dynamic_cast((CTreeItem*)m_tree.GetItemData(hTI)); ASSERT(t); if(!t->m_pPin) return; CComPtr pPinTo; t->m_pPin->ConnectedTo(&pPinTo); CMediaType mt; if(pPinTo) t->m_pPin->ConnectionMediaType(&mt); CAtlArray mts; BeginEnumMediaTypes(t->m_pPin, pEMT, pmt) mts.Add(*pmt); EndEnumMediaTypes(pmt) CMenu m; m.CreatePopupMenu(); int i = 1, mtbase = 1000, mti = mtbase; m.AppendMenu(MF_STRING, i++, !pPinTo ? ResStr(IDS_CONVERT_ENABLESTREAM) : ResStr(IDS_CONVERT_DISABLESTREAM)); m.AppendMenu(MF_STRING | (!pPinTo ? MF_GRAYED : 0), i++, ResStr(IDS_CONVERT_DEMUXSTREAM)); if(mts.GetCount() > 1) { m.AppendMenu(MF_SEPARATOR); for(int i = 0; i < mts.GetCount(); i++) m.AppendMenu(MF_STRING | (mts[i] == mt ? MF_CHECKED : 0), mti++, CMediaTypeEx(mts[i]).ToString()); } m.AppendMenu(MF_SEPARATOR); m.AppendMenu(MF_STRING | (!pPinTo ? MF_GRAYED : 0), i++, ResStr(IDS_CONVERT_PINPROPERTIES)); switch(i = (int)m.TrackPopupMenu(TPM_LEFTBUTTON|TPM_RETURNCMD, p.x, p.y, this)) { case 1: if(pPinTo) { m_pGB->Disconnect(pPinTo); m_pGB->Disconnect(t->m_pPin); } else if(pPinTo = GetFirstDisconnectedPin(m_pMux, PINDIR_INPUT)) m_pGB->ConnectDirect(t->m_pPin, pPinTo, NULL); t->Update(); break; case 2: { UpdateData(); CString ext = _T("raw"); if(mt.subtype == MEDIASUBTYPE_AAC) ext = _T("aac"); else if(mt.subtype == MEDIASUBTYPE_MP3) ext = _T("mp3"); else if(mt.subtype == FOURCCMap(WAVE_FORMAT_MPEG)) ext = _T("m1a"); else if(mt.subtype == MEDIASUBTYPE_MPEG2_AUDIO) ext = _T("m2a"); else if(mt.subtype == MEDIASUBTYPE_WAVE_DOLBY_AC3 || mt.subtype == MEDIASUBTYPE_DOLBY_AC3) ext = _T("ac3"); else if(mt.subtype == MEDIASUBTYPE_WAVE_DTS || mt.subtype == MEDIASUBTYPE_DTS) ext = _T("dts"); else if((mt.subtype == FOURCCMap('1CVA') || mt.subtype == FOURCCMap('1cva')) && mt.formattype == FORMAT_MPEG2_VIDEO) ext = _T("h264"); else if(mt.majortype == MEDIATYPE_Video && (mt.subtype == MEDIASUBTYPE_XVID || mt.subtype == MEDIASUBTYPE_xvid || mt.subtype == MEDIASUBTYPE_XVIX || mt.subtype == MEDIASUBTYPE_xvix)) ext = _T("xvid"); else if(mt.majortype == MEDIATYPE_Video && (mt.subtype == MEDIASUBTYPE_DIVX || mt.subtype == MEDIASUBTYPE_divx || mt.subtype == MEDIASUBTYPE_DX50 || mt.subtype == MEDIASUBTYPE_dx50)) ext = _T("divx"); else if(mt.majortype == MEDIATYPE_Video && (mt.subtype == MEDIASUBTYPE_MP4V || mt.subtype == MEDIASUBTYPE_mp4v || mt.subtype == MEDIASUBTYPE_M4S2 || mt.subtype == MEDIASUBTYPE_m4s2 || mt.subtype == MEDIASUBTYPE_MP4S || mt.subtype == MEDIASUBTYPE_mp4s)) ext = _T("mp4v"); else if(mt.majortype == MEDIATYPE_Video && (mt.subtype == MEDIASUBTYPE_WMV1 || mt.subtype == MEDIASUBTYPE_wmv1)) ext = _T("WMV1"); else if(mt.majortype == MEDIATYPE_Video && (mt.subtype == MEDIASUBTYPE_WMV2 || mt.subtype == MEDIASUBTYPE_wmv2)) ext = _T("WMV2"); else if(mt.majortype == MEDIATYPE_Video && (mt.subtype == MEDIASUBTYPE_WMV3 || mt.subtype == MEDIASUBTYPE_wmv3)) ext = _T("WMV3"); else if(mt.majortype == MEDIATYPE_Video && (mt.subtype == MEDIASUBTYPE_DIV3 || mt.subtype == MEDIASUBTYPE_div3 || mt.subtype == MEDIASUBTYPE_DIV4 || mt.subtype == MEDIASUBTYPE_div4 || mt.subtype == MEDIASUBTYPE_DIV5 || mt.subtype == MEDIASUBTYPE_div5)) ext = _T("div3"); else if(mt.majortype == MEDIATYPE_Video && (mt.subtype == MEDIASUBTYPE_MP43 || mt.subtype == MEDIASUBTYPE_mp43 || mt.subtype == MEDIASUBTYPE_MPG3 || mt.subtype == MEDIASUBTYPE_mpg3)) ext = _T("mp43"); else if(mt.majortype == MEDIATYPE_Video && (mt.subtype == MEDIASUBTYPE_MP42 || mt.subtype == MEDIASUBTYPE_mp42 || mt.subtype == MEDIASUBTYPE_DIV2 || mt.subtype == MEDIASUBTYPE_div2)) ext = _T("mp42"); else if(mt.majortype == MEDIATYPE_Video && (mt.subtype == MEDIASUBTYPE_MP41 || mt.subtype == MEDIASUBTYPE_mp41 || mt.subtype == MEDIASUBTYPE_DIV1 || mt.subtype == MEDIASUBTYPE_div1)) ext = _T("mp41"); else if(mt.majortype == MEDIATYPE_Video && mt.subtype == MEDIASUBTYPE_VP50) ext = _T("vp5"); else if(mt.majortype == MEDIATYPE_Video && (mt.subtype == MEDIASUBTYPE_VP60 || mt.subtype == MEDIASUBTYPE_VP61 || mt.subtype == MEDIASUBTYPE_VP62 || mt.subtype == MEDIASUBTYPE_VP6A || mt.subtype == MEDIASUBTYPE_VP6F)) ext = _T("vp6"); else if(mt.majortype == MEDIATYPE_Video && mt.subtype == MEDIASUBTYPE_VP80) ext = _T("vp8"); else if(mt.majortype == MEDIATYPE_Video && mt.subtype == MEDIASUBTYPE_FLV1) ext = _T("flv"); else if(mt.majortype == MEDIATYPE_Video && mt.subtype == MEDIASUBTYPE_FLV4) ext = _T("flv"); else if(mt.majortype == MEDIATYPE_Video && mt.subtype == MEDIASUBTYPE_SVQ3) ext = _T("svq3"); else if(mt.majortype == MEDIATYPE_Video && mt.subtype == MEDIASUBTYPE_SVQ1) ext = _T("svq1"); else if(mt.majortype == MEDIATYPE_Video && (mt.subtype == MEDIASUBTYPE_H263 || mt.subtype == MEDIASUBTYPE_h263)) ext = _T("h263"); else if(mt.subtype == FOURCCMap('GEPJ') || mt.subtype == FOURCCMap('gepj')) ext = _T("jpg"); else if(mt.majortype == MEDIATYPE_Video && mt.subtype == MEDIASUBTYPE_MPEG2_VIDEO) ext = _T("m2v"); else if(mt.majortype == MEDIATYPE_Video && mt.subtype == MEDIASUBTYPE_MPEG1Payload) ext = _T("m1v"); else if(mt.subtype == MEDIASUBTYPE_UTF8 || mt.majortype == MEDIATYPE_Text) ext = _T("srt"); else if(mt.subtype == MEDIASUBTYPE_SSA) ext = _T("ssa"); else if(mt.subtype == MEDIASUBTYPE_ASS || mt.subtype == MEDIASUBTYPE_ASS2) ext = _T("ass"); else if(mt.subtype == MEDIASUBTYPE_SSF) ext = _T("ssf"); else if(mt.subtype == MEDIASUBTYPE_VOBSUB) ext = _T("sub"); 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"); // TODO: else if... CPath path(m_fn); path.RenameExtension('.' + ext); CFileDialog fd(FALSE, NULL, (LPCTSTR)path, OFN_EXPLORER|OFN_ENABLESIZING|OFN_HIDEREADONLY, ResStr(IDS_CONVERTDLG_0), this, 0); if(fd.DoModal() == IDOK) { if(!ConvertFile(fd.GetPathName(), pPinTo)) { AfxMessageBox(ResStr(IDS_CONVERTDLG_2)); } } } break; case 3: EditProperties(CComQIPtr(pPinTo)); break; default: i -= mtbase; if(i >= 0 && i < mts.GetCount()) { if(pPinTo) { m_pGB->Disconnect(pPinTo); m_pGB->Disconnect(t->m_pPin); } else { pPinTo = GetFirstDisconnectedPin(m_pMux, PINDIR_INPUT); } HRESULT hr = m_pGB->ConnectDirect(t->m_pPin, pPinTo, &mts[i]); if(FAILED(hr)) { AfxMessageBox(ResStr(IDS_CONVERTDLG_3)); if(mt.majortype != GUID_NULL) hr = m_pGB->ConnectDirect(t->m_pPin, pPinTo, &mt); } t->Update(); } break; } } void CConvertDlg::ShowResourceFolderPopup(HTREEITEM hTI, CPoint p) { CTreeItemResourceFolder* t = dynamic_cast((CTreeItem*)m_tree.GetItemData(hTI)); ASSERT(t); CMenu m; m.CreatePopupMenu(); int i = 1; m.AppendMenu(MF_STRING, i++, ResStr(IDS_CONVERT_ADDRESOURCE)); if(m_tree.ItemHasChildren(*t)) { m.AppendMenu(MF_SEPARATOR); m.AppendMenu(MF_STRING, i++, ResStr(IDS_CONVERT_REMOVEALL)); } switch((int)m.TrackPopupMenu(TPM_LEFTBUTTON|TPM_RETURNCMD, p.x, p.y, this)) { case 1: { CFileDialog fd(TRUE, NULL, NULL, OFN_EXPLORER|OFN_ENABLESIZING|OFN_HIDEREADONLY, ResStr(IDS_CONVERTDLG_4), this, 0); if(fd.DoModal() == IDOK) { CString fn = fd.GetPathName(); if(FILE* f = _tfopen(fn, _T("rb"))) { CDSMResource res; CPath path(fn); path.StripPath(); res.name = (LPCTSTR)path; CRegKey key; TCHAR mime[256]; ULONG len = countof(mime); if(ERROR_SUCCESS == key.Open(HKEY_CLASSES_ROOT, path.GetExtension().MakeLower(), KEY_READ) && ERROR_SUCCESS == key.QueryStringValue(_T("Content Type"), mime, &len)) res.mime = mime; CTreeItemResource* t = DNew CTreeItemResource(res, m_tree, hTI); m_pTIs.AddTail(t); if(EditResource(t)) { fseek(f, 0, 2); long size = ftell(f); fseek(f, 0, 0); t->m_res.data.SetCount(size); for(BYTE* ptr = t->m_res.data.GetData(),* end = ptr + size; size > 0 && end - ptr >= size && fread(ptr, min(size, 1024), 1, f) > 0; ptr += 1024, size -= 1024); fclose(f); } else { DeleteItem(*t); } } else { AfxMessageBox(ResStr(IDS_CONVERTDLG_5)); } } } break; case 2: DeleteChildren(hTI); break; } } void CConvertDlg::ShowResourcePopup(HTREEITEM hTI, CPoint p) { CTreeItemResource* t = dynamic_cast((CTreeItem*)m_tree.GetItemData(hTI)); ASSERT(t); CMenu m; m.CreatePopupMenu(); int i = 1; m.AppendMenu(MF_STRING, i++, ResStr(IDS_CONVERT_REMOVE)); m.AppendMenu(MF_STRING, i++, ResStr(IDS_CONVERT_SAVEAS)); if(AfxGetAppSettings().fEnableWebServer) m.AppendMenu(MF_STRING, 1000, ResStr(IDS_CONVERT_LAUNCHINBROWSER)); m.AppendMenu(MF_SEPARATOR); m.AppendMenu(MF_STRING, i++, ResStr(IDS_CONVERT_RESOURCEPROPERTIES)); switch((int)m.TrackPopupMenu(TPM_LEFTBUTTON|TPM_RETURNCMD, p.x, p.y, this)) { case 1: DeleteItem(*t); break; case 2: { CFileDialog fd(FALSE, NULL, CString(t->m_res.name), OFN_EXPLORER|OFN_ENABLESIZING|OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, ResStr(IDS_CONVERTDLG_4), this, 0); if(fd.DoModal() == IDOK) { if(FILE* f = _tfopen(fd.GetPathName(), _T("wb"))) { fwrite(t->m_res.data.GetData(), 1, t->m_res.data.GetCount(), f); fclose(f); } } } break; case 3: EditResource(t); break; case 1000: { CString url; url.Format(_T("http://localhost:%d/convres.html?id=%x"), AfxGetAppSettings().nWebServerPort, (DWORD)&t->m_res); ShellExecute(NULL, _T("open"), url, NULL, NULL, SW_SHOWDEFAULT); } break; } } bool CConvertDlg::EditProperties(IDSMPropertyBag* pPB) { CConvertPropsDlg dlg(!!CComQIPtr(pPB), this); ULONG props; if(FAILED(pPB->CountProperties(&props))) props = 0; for(ULONG i = 0; i < props; i++) { PROPBAG2 PropBag; memset(&PropBag, 0, sizeof(PropBag)); ULONG cPropertiesReturned = 0; if(FAILED(pPB->GetPropertyInfo(i, 1, &PropBag, &cPropertiesReturned))) continue; HRESULT hr; CComVariant var; if(SUCCEEDED(pPB->Read(1, &PropBag, NULL, &var, &hr)) && SUCCEEDED(hr)) dlg.m_props[CString(PropBag.pstrName)] = CString(var); CoTaskMemFree(PropBag.pstrName); } if(IDOK != dlg.DoModal()) return false; pPB->DelAllProperties(); POSITION pos = dlg.m_props.GetStartPosition(); while(pos) { CString key, value; dlg.m_props.GetNextAssoc(pos, key, value); pPB->SetProperty(CStringW(key), CStringW(value)); } return true; } bool CConvertDlg::EditResource(CTreeItemResource* t) { CConvertResDlg dlg(this); dlg.m_name = t->m_res.name; dlg.m_mime = t->m_res.mime; dlg.m_desc = t->m_res.desc; if(IDOK != dlg.DoModal()) return false; t->m_res.name = dlg.m_name; t->m_res.mime = dlg.m_mime; t->m_res.desc = dlg.m_desc; t->Update(); return true; } void CConvertDlg::ShowChapterFolderPopup(HTREEITEM hTI, CPoint p) { CTreeItemChapterFolder* t = dynamic_cast((CTreeItem*)m_tree.GetItemData(hTI)); ASSERT(t); CMenu m; m.CreatePopupMenu(); int i = 1; m.AppendMenu(MF_STRING, i++, ResStr(IDS_CONVERT_ADDCHAPTER)); if(m_tree.ItemHasChildren(*t)) { m.AppendMenu(MF_SEPARATOR); m.AppendMenu(MF_STRING, i++, ResStr(IDS_CONVERT_REMOVEALL)); } switch((int)m.TrackPopupMenu(TPM_LEFTBUTTON|TPM_RETURNCMD, p.x, p.y, this)) { case 1: { CDSMChapter chap; CTreeItemChapter* t = DNew CTreeItemChapter(CDSMChapter(0, L""), m_tree, hTI); m_pTIs.AddTail(t); if(!EditChapter(t)) DeleteItem(*t); } break; case 2: DeleteChildren(hTI); break; } } void CConvertDlg::ShowChapterPopup(HTREEITEM hTI, CPoint p) { CTreeItemChapter* t = dynamic_cast((CTreeItem*)m_tree.GetItemData(hTI)); ASSERT(t); CMenu m; m.CreatePopupMenu(); int i = 1; m.AppendMenu(MF_STRING, i++, ResStr(IDS_CONVERT_REMOVE)); m.AppendMenu(MF_SEPARATOR); m.AppendMenu(MF_STRING, i++, ResStr(IDS_CONVERT_CHAPTERPROPERTIES)); switch((int)m.TrackPopupMenu(TPM_LEFTBUTTON|TPM_RETURNCMD, p.x, p.y, this)) { case 1: DeleteItem(hTI); break; case 2: EditChapter(t); break; } } bool CConvertDlg::EditChapter(CTreeItemChapter* t) { CConvertChapDlg dlg(this); int h = (int)(t->m_chap.rt/10000000/60/60); int m = (int)(t->m_chap.rt/10000000/60%60); int s = (int)(t->m_chap.rt/10000000%60); int ms = (int)(t->m_chap.rt/10000%1000); dlg.m_name = t->m_chap.name; dlg.m_time.Format(_T("%02d:%02d:%02d.%03d"), h, m, s, ms); if(IDOK != dlg.DoModal()) return false; TCHAR c; if(_stscanf(dlg.m_time, _T("%d%c%d%c%d%c%d"), &h, &c, &m, &c, &s, &c, &ms) != 7) return false; t->m_chap.name = dlg.m_name; t->m_chap.rt = ((((__int64)h*60+m)*60+s)*1000+ms)*10000; t->Update(); return true; } void CConvertDlg::DoDataExchange(CDataExchange* pDX) { __super::DoDataExchange(pDX); DDX_Control(pDX, IDC_TREE1, m_tree); DDX_Text(pDX, IDC_EDIT1, m_fn); } BOOL CConvertDlg::PreTranslateMessage(MSG* pMsg) { if(pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_ESCAPE) return TRUE; return __super::PreTranslateMessage(pMsg); } BOOL CConvertDlg::OnInitDialog() { __super::OnInitDialog(); SetIcon(AfxGetApp()->LoadIcon(IDR_MAINFRAME), TRUE); SetIcon(AfxGetApp()->LoadIcon(IDR_MAINFRAME), FALSE); AddAnchor(IDC_TREE1, TOP_LEFT, BOTTOM_RIGHT); AddAnchor(IDC_EDIT1, BOTTOM_LEFT, BOTTOM_RIGHT); AddAnchor(IDC_BUTTON1, BOTTOM_RIGHT); AddAnchor(IDC_HLINE, BOTTOM_LEFT, BOTTOM_RIGHT); AddAnchor(IDC_BUTTON2, BOTTOM_CENTER); AddAnchor(IDC_BUTTON3, BOTTOM_CENTER); AddAnchor(IDC_BUTTON4, BOTTOM_CENTER); CSize s(400, 200); SetMinTrackSize(s); m_streamtypesbm.LoadBitmap(IDB_STREAMTYPES); m_streamtypes.Create(16, 18, ILC_MASK|ILC_COLOR32, 0, 4); m_streamtypes.Add(&m_streamtypesbm, 0xffffff); m_tree.SetImageList(&m_streamtypes, TVSIL_NORMAL); GetWindowText(m_title); m_nIDEventStatus = SetTimer(1, 1000, NULL); HRESULT hr; m_pMux = DNew CDSMMuxerFilter(NULL, &hr, false, false); m_pGB = DNew CFGManagerMuxer(_T("CFGManagerMuxer"), NULL); m_pGB->AddToROT(); if(FAILED(m_pGB->AddFilter(m_pMux, L"Mux")) || !(m_pMC = m_pGB) || !(m_pME = m_pGB) || !(m_pMS = m_pMux) || FAILED(m_pME->SetNotifyWindow((OAHWND)m_hWnd, WM_GRAPHNOTIFY, 0))) { MessageBeep((UINT)-1); SendMessage(WM_CLOSE); return TRUE; } return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE } void CConvertDlg::OnOK() { } BEGIN_MESSAGE_MAP(CConvertDlg, CResizableDialog) ON_MESSAGE(WM_GRAPHNOTIFY, OnGraphNotify) ON_WM_DROPFILES() ON_WM_CLOSE() ON_NOTIFY(NM_CLICK, IDC_TREE1, OnNMClickTree1) ON_NOTIFY(NM_RCLICK, IDC_TREE1, OnNMRclickTree1) ON_NOTIFY(NM_DBLCLK, IDC_TREE1, OnNMDblclkTree1) ON_BN_CLICKED(IDC_BUTTON1, OnBnClickedButton1) ON_UPDATE_COMMAND_UI(IDC_BUTTON1, OnUpdateButton1) ON_WM_TIMER() ON_BN_CLICKED(IDC_BUTTON2, OnBnClickedButton2) ON_UPDATE_COMMAND_UI(IDC_BUTTON2, OnUpdateButton2) ON_BN_CLICKED(IDC_BUTTON3, OnBnClickedButton3) ON_UPDATE_COMMAND_UI(IDC_BUTTON3, OnUpdateButton3) ON_BN_CLICKED(IDC_BUTTON4, OnBnClickedButton4) ON_UPDATE_COMMAND_UI(IDC_BUTTON4, OnUpdateButton4) END_MESSAGE_MAP() // CConvertDlg message handlers LRESULT CConvertDlg::OnGraphNotify(WPARAM wParam, LPARAM lParam) { HRESULT hr = S_OK; LONG evCode, evParam1, evParam2; while(m_pME && SUCCEEDED(m_pME->GetEvent(&evCode, (LONG_PTR*)&evParam1, (LONG_PTR*)&evParam2, 0))) { hr = m_pME->FreeEventParams(evCode, evParam1, evParam2); bool fStop = false; if(EC_COMPLETE == evCode) { fStop = true; } else if(EC_ERRORABORT == evCode) { fStop = true; CString errmsg; LPVOID lpMsgBuf; if(FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, NULL, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL)) { errmsg = (LPCTSTR)lpMsgBuf; LocalFree(lpMsgBuf); } CString str; str.Format(ResStr(IDS_CONVERTDLG_7), evParam1); if(!errmsg.IsEmpty()) str += _T(" (") + errmsg + _T(")"); AfxMessageBox(str, MB_OK); } if(fStop && m_pMC) { m_pMC->Stop(); m_tree.EnableWindow(TRUE); } } return hr; } void CConvertDlg::OnDropFiles(HDROP hDropInfo) { for(int i = 0, j = DragQueryFile(hDropInfo, 0xffffffff, 0, 0); i < j; i++) { CString fn; fn.ReleaseBufferSetLength(DragQueryFile(hDropInfo, i, fn.GetBuffer(MAX_PATH), MAX_PATH)); AddFile(fn); } __super::OnDropFiles(hDropInfo); } void CConvertDlg::OnClose() { HTREEITEM hTI = m_tree.GetRootItem(); while(hTI) { HTREEITEM hTINext = m_tree.GetNextSiblingItem(hTI); DeleteItem(hTI); hTI = hTINext; } m_pGB->RemoveFromROT(); m_pGB = NULL; __super::OnClose(); } void CConvertDlg::OnNMClickTree1(NMHDR* pNMHDR, LRESULT* pResult) { CPoint sp, cp; HTREEITEM hTI = HitTest(sp, cp); if(!hTI) return; m_tree.SelectItem(hTI); *pResult = 0; } void CConvertDlg::OnNMRclickTree1(NMHDR* pNMHDR, LRESULT* pResult) { CPoint sp, cp; HTREEITEM hTI = HitTest(sp, cp); if(hTI) { m_tree.SelectItem(hTI); CTreeItem* t = (CTreeItem*)m_tree.GetItemData(hTI); if(dynamic_cast(t)) ShowPinPopup(hTI, sp); else if(dynamic_cast(t)) ShowFilePopup(hTI, sp); else if(dynamic_cast(t)) ShowResourceFolderPopup(hTI, sp); else if(dynamic_cast(t)) ShowResourcePopup(hTI, sp); else if(dynamic_cast(t)) ShowChapterFolderPopup(hTI, sp); else if(dynamic_cast(t)) ShowChapterPopup(hTI, sp); } else { ShowPopup(sp); } *pResult = 0; } void CConvertDlg::OnNMDblclkTree1(NMHDR *pNMHDR, LRESULT *pResult) { CPoint sp, cp; HTREEITEM hTI = HitTest(sp, cp); if(hTI) { CTreeItem* t = (CTreeItem*)m_tree.GetItemData(hTI); if(CTreeItemPin* t2 = dynamic_cast(t)) { CComPtr pPinTo; t2->m_pPin->ConnectedTo(&pPinTo); if(CComQIPtr pPB = pPinTo) EditProperties(pPB); } else if(CTreeItemResource* t2 = dynamic_cast(t)) { EditResource(t2); } else if(CTreeItemChapter* t2 = dynamic_cast(t)) { EditChapter(t2); } } *pResult = 0; } void CConvertDlg::OnBnClickedButton1() { UpdateData(); CFileDialog fd(FALSE, _T(".dsm"), m_fn, OFN_EXPLORER|OFN_ENABLESIZING|OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, ResStr(IDS_CONVERTDLG_8), this, 0); if(fd.DoModal() == IDOK) { m_fn = fd.GetPathName(); UpdateData(FALSE); } } void CConvertDlg::OnUpdateButton1(CCmdUI* pCmdUI) { OAFilterState fs; pCmdUI->Enable(m_pMC && SUCCEEDED(m_pMC->GetState(0, &fs)) && fs == State_Stopped); } void CConvertDlg::OnTimer(UINT_PTR nIDEvent) { if(nIDEvent == m_nIDEventStatus && m_pMS && m_pMC) { OAFilterState fs; if(SUCCEEDED(m_pMC->GetState(0, &fs)) && fs != State_Stopped) { GUID tf; m_pMS->GetTimeFormat(&tf); REFERENCE_TIME rtCur, rtDur; HRESULT hr = m_pMS->GetDuration(&rtDur); m_pMS->GetCurrentPosition(&rtCur); CString str; if(hr == S_OK && rtDur != 0) str.Format(_T("%.2f%%"), 1.0 * (rtCur * 100) / rtDur); else if(hr == S_OK && rtDur == 0) str = _T("Live"); else if(tf == TIME_FORMAT_BYTE) str.Format(_T("%.2fKB"), 1.0 * rtCur / 1024); 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); else str = ResStr(IDS_AG_PLEASE_WAIT); SetWindowText(ResStr(IDS_AG_CONVERTING) + str); } else { SetWindowText(m_title); } } __super::OnTimer(nIDEvent); } void CConvertDlg::OnBnClickedButton2() { OAFilterState fs; if(FAILED(m_pMC->GetState(0, &fs))) return; if(fs != State_Stopped) { m_pMC->Run(); return; } UpdateData(); if(!ConvertFile(m_fn)) { AfxMessageBox(ResStr(IDS_CONVERTDLG_2)); } } void CConvertDlg::OnUpdateButton2(CCmdUI* pCmdUI) { int nIn, nOut, nInC, nOutC; CountPins(m_pMux, nIn, nOut, nInC, nOutC); OAFilterState fs; pCmdUI->Enable(nInC > 0 && GetDlgItem(IDC_EDIT1)->GetWindowTextLength() > 0 && m_pMS && m_pMC && SUCCEEDED(m_pMC->GetState(0, &fs)) && fs != State_Running); } void CConvertDlg::OnBnClickedButton3() { if(m_pMC) m_pMC->Pause(); } void CConvertDlg::OnUpdateButton3(CCmdUI* pCmdUI) { OAFilterState fs; pCmdUI->Enable(m_pMC && SUCCEEDED(m_pMC->GetState(0, &fs)) && fs == State_Running); } void CConvertDlg::OnBnClickedButton4() { if(m_pMC) m_pMC->Stop(); m_tree.EnableWindow(TRUE); } void CConvertDlg::OnUpdateButton4(CCmdUI* pCmdUI) { OAFilterState fs; pCmdUI->Enable(m_pMC && SUCCEEDED(m_pMC->GetState(0, &fs)) && fs != State_Stopped); } // // CFilterTreeCtrl // CFilterTreeCtrl::CFilterTreeCtrl() { } void CFilterTreeCtrl::PreSubclassWindow() { EnableToolTips(TRUE); __super::PreSubclassWindow(); } INT_PTR CFilterTreeCtrl::OnToolHitTest(CPoint p, TOOLINFO* pTI) const { UINT nFlags; HTREEITEM hTI = HitTest(p, &nFlags); if(nFlags & TVHT_ONITEM) { CRect r; GetItemRect(hTI, r, TRUE); pTI->hwnd = m_hWnd; pTI->uId = (UINT)hTI; pTI->lpszText = LPSTR_TEXTCALLBACK; pTI->rect = r; return pTI->uId; } return -1; } BEGIN_MESSAGE_MAP(CFilterTreeCtrl, CTreeCtrl) ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText) ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipText) END_MESSAGE_MAP() BOOL CFilterTreeCtrl::OnToolTipText(UINT id, NMHDR* pNMHDR, LRESULT* pResult) { TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR; TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR; UINT nID = pNMHDR->idFrom; if(nID == (UINT)m_hWnd && (pNMHDR->code == TTN_NEEDTEXTA && (pTTTA->uFlags & TTF_IDISHWND) || pNMHDR->code == TTN_NEEDTEXTW && (pTTTW->uFlags & TTF_IDISHWND))) return FALSE; ::SendMessage(pNMHDR->hwndFrom, TTM_SETMAXTIPWIDTH, 0, (LPARAM)(INT)1000); HTREEITEM hTI = (HTREEITEM)nID; CString str; static CStringA m_strTipTextA; static CStringW m_strTipTextW; CConvertDlg::CTreeItem* t = (CConvertDlg::CTreeItem*)GetItemData(hTI); if(!t || !t->ToolTip(str)) return FALSE; m_strTipTextA = str; m_strTipTextW = str; if(pNMHDR->code == TTN_NEEDTEXTA) pTTTA->lpszText = (LPSTR)(LPCSTR)m_strTipTextA; else pTTTW->lpszText = (LPWSTR)(LPCWSTR)m_strTipTextW; *pResult = 0; return TRUE; // message was handled } // // CConvertDlg::CTreeItem* // CConvertDlg::CTreeItem::CTreeItem(CTreeCtrl& tree, HTREEITEM hTIParent) : m_tree(tree) { m_hTI = m_tree.InsertItem(_T(""), hTIParent); m_tree.SetItemData(m_hTI, (DWORD_PTR)this); Update(); } CConvertDlg::CTreeItem::~CTreeItem() { } void CConvertDlg::CTreeItem::SetLabel(LPCTSTR label) { m_tree.SetItemText(m_hTI, label); } void CConvertDlg::CTreeItem::SetImage(int nImage, int nSelectedImage) { m_tree.SetItemImage(m_hTI, nImage, nSelectedImage); } // CConvertDlg::CTreeItemFilter::CTreeItemFilter(IBaseFilter* pBF, CTreeCtrl& tree, HTREEITEM hTIParent) : CTreeItem(tree, hTIParent) , m_pBF(pBF) { Update(); } void CConvertDlg::CTreeItemFilter::Update() { SetLabel(CString(GetFilterName(m_pBF))); } // CConvertDlg::CTreeItemFile::CTreeItemFile(CString fn, IBaseFilter* pBF, CTreeCtrl& tree, HTREEITEM hTIParent) : CTreeItemFilter(pBF, tree, hTIParent) , m_fn(fn) { Update(); } void CConvertDlg::CTreeItemFile::Update() { CPath path = m_fn; path.StripPath(); SetLabel(path); } bool CConvertDlg::CTreeItemFile::ToolTip(CString& str) { str = m_fn; return true; } // CConvertDlg::CTreeItemPin::CTreeItemPin(IPin* pPin, CTreeCtrl& tree, HTREEITEM hTIParent) : CTreeItem(tree, hTIParent) , m_pPin(pPin) { Update(); } void CConvertDlg::CTreeItemPin::Update() { if(!m_pPin) { ASSERT(0); return; } CString label = GetPinName(m_pPin); if(!IsConnected()) label = _T("[D] ") + label; SetLabel(label); CMediaType mt; if(S_OK == m_pPin->ConnectionMediaType(&mt)) { if(mt.majortype == MEDIATYPE_Video) SetImage(1, 1); else if(mt.majortype == MEDIATYPE_Audio) SetImage(2, 2); else if(mt.majortype == MEDIATYPE_Text || mt.majortype == MEDIATYPE_Subtitle) SetImage(3, 3); } } bool CConvertDlg::CTreeItemPin::ToolTip(CString& str) { CMediaTypeEx mt; if(FAILED(m_pPin->ConnectionMediaType(&mt))) return false; str = mt.ToString(m_pPin); return true; } bool CConvertDlg::CTreeItemPin::IsConnected() { CComPtr pPinTo; return m_pPin && SUCCEEDED(m_pPin->ConnectedTo(&pPinTo)) && pPinTo; } // CConvertDlg::CTreeItemResourceFolder::CTreeItemResourceFolder(CTreeCtrl& tree, HTREEITEM hTIParent) : CTreeItem(tree, hTIParent) { Update(); } void CConvertDlg::CTreeItemResourceFolder::Update() { SetLabel(ResStr(IDS_AG_RESOURCES)); } bool CConvertDlg::CTreeItemResourceFolder::ToolTip(CString& str) { if(!m_tree.ItemHasChildren(m_hTI)) return false; int files = 0; float size = 0; HTREEITEM hChildItem = m_tree.GetChildItem(m_hTI); while(hChildItem != NULL) { HTREEITEM hNextItem = m_tree.GetNextItem(hChildItem, TVGN_NEXT); if(CTreeItemResource* t = dynamic_cast((CTreeItem*)m_tree.GetItemData(hChildItem))) size += t->m_res.data.GetCount(), files++; hChildItem = hNextItem; } size /= 1024; if(size < 1024) str.Format(ResStr(IDS_CONVERTDLG_13), files, size); else str.Format(ResStr(IDS_CONVERTDLG_14), files, size/1024); return true; } // CConvertDlg::CTreeItemResource::CTreeItemResource(const CDSMResource& res, CTreeCtrl& tree, HTREEITEM hTIParent) : CTreeItem(tree, hTIParent) { m_res = res; Update(); } CConvertDlg::CTreeItemResource::~CTreeItemResource() { } void CConvertDlg::CTreeItemResource::Update() { SetLabel(CString(m_res.name)); CStringW mime = m_res.mime; mime.Trim(); mime.MakeLower(); if(mime == L"application/x-truetype-font") SetImage(4, 4); else if(mime.Find(L"text/") == 0) SetImage(5, 5); else SetImage(6, 6); } bool CConvertDlg::CTreeItemResource::ToolTip(CString& str) { if(!m_res.mime.IsEmpty()) str = CString(m_res.mime) + _T("\r\n\r\n"); if(!m_res.desc.IsEmpty()) str += CString(m_res.desc); str.Trim(); return true; } // CConvertDlg::CTreeItemChapterFolder::CTreeItemChapterFolder(CTreeCtrl& tree, HTREEITEM hTIParent) : CTreeItem(tree, hTIParent) { Update(); } void CConvertDlg::CTreeItemChapterFolder::Update() { SetLabel(ResStr(IDS_AG_CHAPTERS)); } // CConvertDlg::CTreeItemChapter::CTreeItemChapter(const CDSMChapter& chap, CTreeCtrl& tree, HTREEITEM hTIParent) : CTreeItem(tree, hTIParent) { m_chap = chap; Update(); } void CConvertDlg::CTreeItemChapter::Update() { REFERENCE_TIME rt = m_chap.rt; rt /= 10000; int ms = (int)(rt%1000); rt /= 1000; int s = (int)(rt%60); rt /= 60; int m = (int)(rt%60); rt /= 60; int h = (int)(rt); CString label; label.Format(_T("%02d:%02d:%02d.%03d - %s"), h, m, s, ms, CString(m_chap.name)); SetLabel(label); SetImage(7, 7); }