asf2mkvDlg.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:15k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /* 
  2.  * Copyright (C) 2003-2005 Gabest
  3.  * http://www.gabest.org
  4.  *
  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.
  14.  *   
  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
  19.  *
  20.  */
  21. // asf2mkvDlg.cpp : implementation file
  22. //
  23. #include "stdafx.h"
  24. #include "asf2mkv.h"
  25. #include "asf2mkvDlg.h"
  26. #ifdef _DEBUG
  27. #define new DEBUG_NEW
  28. #endif
  29. #include <initguid.h>
  30. #include ".asf2mkvdlg.h"
  31. //  {6B6D0800-9ADA-11d0-A520-00A0D10129C0}
  32. DEFINE_GUID(CLSID_NetShowSource, 
  33. 0x6b6d0800, 0x9ada, 0x11d0, 0xa5, 0x20, 0x0, 0xa0, 0xd1, 0x1, 0x29, 0xc0);
  34. // CAboutDlg dialog used for App About
  35. class CAboutDlg : public CDialog
  36. {
  37. public:
  38. CAboutDlg();
  39. // Dialog Data
  40. enum { IDD = IDD_ABOUTBOX };
  41. protected:
  42. virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
  43. // Implementation
  44. protected:
  45. DECLARE_MESSAGE_MAP()
  46. };
  47. CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
  48. {
  49. }
  50. void CAboutDlg::DoDataExchange(CDataExchange* pDX)
  51. {
  52. CDialog::DoDataExchange(pDX);
  53. }
  54. BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
  55. END_MESSAGE_MAP()
  56. // CUrlDropTarget
  57. BEGIN_MESSAGE_MAP(CUrlDropTarget, COleDropTarget)
  58. END_MESSAGE_MAP()
  59. DROPEFFECT CUrlDropTarget::OnDragEnter(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point)
  60. {
  61. return DROPEFFECT_NONE;
  62. }
  63. DROPEFFECT CUrlDropTarget::OnDragOver(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point)
  64. {
  65. UINT CF_URL = RegisterClipboardFormat(_T("UniformResourceLocator"));
  66. return pDataObject->IsDataAvailable(CF_URL) ? DROPEFFECT_COPY : DROPEFFECT_NONE;
  67. }
  68. BOOL CUrlDropTarget::OnDrop(CWnd* pWnd, COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point)
  69. {
  70. UINT CF_URL = RegisterClipboardFormat(_T("UniformResourceLocator"));
  71. BOOL bResult = FALSE;
  72. if(pDataObject->IsDataAvailable(CF_URL)) 
  73. {
  74. FORMATETC fmt = {CF_URL, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  75. if(HGLOBAL hGlobal = pDataObject->GetGlobalData(CF_URL, &fmt))
  76. {
  77. LPCSTR pText = (LPCSTR)GlobalLock(hGlobal);
  78. if(AfxIsValidString(pText))
  79. {
  80. AfxGetMainWnd()->SendMessage(WM_OPENURL, 0, (LPARAM)pText);
  81. GlobalUnlock(hGlobal);
  82. bResult = TRUE;
  83. }
  84. }
  85. }
  86. return bResult;
  87. }
  88. DROPEFFECT CUrlDropTarget::OnDropEx(CWnd* pWnd, COleDataObject* pDataObject, DROPEFFECT dropDefault, DROPEFFECT dropList, CPoint point)
  89. {
  90. return (DROPEFFECT)-1;
  91. }
  92. void CUrlDropTarget::OnDragLeave(CWnd* pWnd)
  93. {
  94. }
  95. DROPEFFECT CUrlDropTarget::OnDragScroll(CWnd* pWnd, DWORD dwKeyState, CPoint point)
  96. {
  97. return DROPEFFECT_NONE;
  98. }
  99. // Casf2mkvDlg dialog
  100. #define WM_GRAPHNOTIFY (WM_APP+1)
  101. Casf2mkvDlg::Casf2mkvDlg(CWnd* pParent /*=NULL*/)
  102. : CResizableDialog(Casf2mkvDlg::IDD, pParent)
  103. , m_fRecording(false)
  104. , m_mru(0, _T("MRU"), _T("file%d"), 20, 10)
  105. {
  106. m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  107. }
  108. void Casf2mkvDlg::DoDataExchange(CDataExchange* pDX)
  109. {
  110. __super::DoDataExchange(pDX);
  111. DDX_Control(pDX, IDC_COMBO1, m_combo);
  112. DDX_Control(pDX, IDC_STATIC1, m_video);
  113. }
  114. void Casf2mkvDlg::SetupCombo()
  115. {
  116. m_combo.ResetContent();
  117. for(int i = 0; i < m_mru.GetSize(); i++)
  118. if(!m_mru[i].IsEmpty())
  119. m_combo.AddString(m_mru[i]);
  120. }
  121. void Casf2mkvDlg::SetVideoRect()
  122. {
  123. if(pVW)
  124. {
  125. CRect r;
  126. m_video.GetWindowRect(r);
  127. r -= r.TopLeft();
  128. pVW->SetWindowPosition(r.left, r.top, r.Width(), r.Height());
  129. }
  130. }
  131. BEGIN_MESSAGE_MAP(Casf2mkvDlg, CResizableDialog)
  132. ON_WM_SYSCOMMAND()
  133. ON_WM_PAINT()
  134. ON_WM_QUERYDRAGICON()
  135. ON_MESSAGE(WM_GRAPHNOTIFY, OnGraphNotify)
  136. ON_BN_CLICKED(IDC_BUTTON1, OnRecord)
  137. ON_UPDATE_COMMAND_UI(IDC_BUTTON1, OnUpdateRecord)
  138. ON_UPDATE_COMMAND_UI(IDC_COMBO1, OnUpdateFileName)
  139. ON_UPDATE_COMMAND_UI(IDC_BUTTON2, OnUpdateSettings)
  140. ON_UPDATE_COMMAND_UI(IDC_CHECK2, OnUpdateSettings)
  141. ON_WM_SIZE()
  142. ON_WM_TIMER()
  143. ON_BN_CLICKED(IDC_BUTTON2, OnBnClickedButton2)
  144. ON_MESSAGE(WM_APP, OnUrlOpen)
  145. END_MESSAGE_MAP()
  146. // Casf2mkvDlg message handlers
  147. BOOL Casf2mkvDlg::OnInitDialog()
  148. {
  149. __super::OnInitDialog();
  150. // Add "About..." menu item to system menu.
  151. // IDM_ABOUTBOX must be in the system command range.
  152. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
  153. ASSERT(IDM_ABOUTBOX < 0xF000);
  154. CMenu* pSysMenu = GetSystemMenu(FALSE);
  155. if (pSysMenu != NULL)
  156. {
  157. CString strAboutMenu;
  158. strAboutMenu.LoadString(IDS_ABOUTBOX);
  159. if (!strAboutMenu.IsEmpty())
  160. {
  161. pSysMenu->AppendMenu(MF_SEPARATOR);
  162. pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
  163. }
  164. }
  165. // Set the icon for this dialog.  The framework does this automatically
  166. //  when the application's main window is not a dialog
  167. SetIcon(m_hIcon, TRUE); // Set big icon
  168. SetIcon(m_hIcon, FALSE); // Set small icon
  169. // TODO: Add extra initialization here
  170. AddAnchor(IDC_STATIC1, TOP_LEFT, BOTTOM_RIGHT);
  171. AddAnchor(IDC_COMBO1, BOTTOM_LEFT, BOTTOM_RIGHT);
  172. AddAnchor(IDC_BUTTON1, BOTTOM_RIGHT);
  173. AddAnchor(IDC_BUTTON2, BOTTOM_RIGHT);
  174. m_mru.ReadList();
  175. SetupCombo();
  176. m_video.ModifyStyle(0, WS_CLIPCHILDREN);
  177. SetWindowText(ResStr(IDS_TITLE));
  178. m_urlDropTarget.Register(this);
  179. return TRUE;  // return TRUE  unless you set the focus to a control
  180. }
  181. BOOL Casf2mkvDlg::DestroyWindow()
  182. {
  183. m_urlDropTarget.Revoke();
  184. return __super::DestroyWindow();
  185. }
  186. void Casf2mkvDlg::OnSysCommand(UINT nID, LPARAM lParam)
  187. {
  188. if ((nID & 0xFFF0) == IDM_ABOUTBOX)
  189. {
  190. CAboutDlg dlgAbout;
  191. dlgAbout.DoModal();
  192. }
  193. else
  194. {
  195. __super::OnSysCommand(nID, lParam);
  196. }
  197. }
  198. // If you add a minimize button to your dialog, you will need the code below
  199. //  to draw the icon.  For MFC applications using the document/view model,
  200. //  this is automatically done for you by the framework.
  201. void Casf2mkvDlg::OnPaint() 
  202. {
  203. if (IsIconic())
  204. {
  205. CPaintDC dc(this); // device context for painting
  206. SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
  207. // Center icon in client rectangle
  208. int cxIcon = GetSystemMetrics(SM_CXICON);
  209. int cyIcon = GetSystemMetrics(SM_CYICON);
  210. CRect rect;
  211. GetClientRect(&rect);
  212. int x = (rect.Width() - cxIcon + 1) / 2;
  213. int y = (rect.Height() - cyIcon + 1) / 2;
  214. // Draw the icon
  215. dc.DrawIcon(x, y, m_hIcon);
  216. }
  217. else
  218. {
  219. __super::OnPaint();
  220. }
  221. }
  222. // The system calls this function to obtain the cursor to display while the user drags
  223. //  the minimized window.
  224. HCURSOR Casf2mkvDlg::OnQueryDragIcon()
  225. {
  226. return static_cast<HCURSOR>(m_hIcon);
  227. }
  228. LRESULT Casf2mkvDlg::OnGraphNotify(WPARAM wParam, LPARAM lParam)
  229. {
  230.     HRESULT hr = S_OK;
  231. LONG evCode, evParam1, evParam2;
  232.     while(pME && SUCCEEDED(pME->GetEvent(&evCode, (LONG_PTR*)&evParam1, (LONG_PTR*)&evParam2, 0)))
  233.     {
  234. hr = pME->FreeEventParams(evCode, evParam1, evParam2);
  235.         if(EC_COMPLETE == evCode)
  236.         {
  237. if(m_fRecording)
  238. {
  239. OnRecord();
  240. break;
  241. }
  242.         }
  243. }
  244.     return hr;
  245. }
  246. void Casf2mkvDlg::OnRecord()
  247. {
  248. UpdateData();
  249. HRESULT hr;
  250. if(!m_fRecording)
  251. {
  252. m_fRecording = true;
  253. UpdateDialogControls(this, FALSE);
  254. hr = E_FAIL;
  255. do
  256. {
  257. // i/o
  258. CString src;
  259. m_combo.GetWindowText(src);
  260. CFileDialog fd(
  261. FALSE, _T("mkv"), m_dst, 
  262. OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_EXPLORER|OFN_ENABLESIZING, 
  263. _T("Matroska file (*.mkv;*.mka)|*.mkv;*.mka||"), 
  264. this);
  265. if(fd.DoModal() != IDOK) break;
  266. m_dst = fd.GetPathName();
  267. m_mru.Add(src);
  268. m_mru.WriteList();
  269. SetupCombo();
  270. m_combo.SetWindowText(src);
  271. if(src.Trim().IsEmpty() || m_dst.Trim().IsEmpty()) 
  272. break;
  273. // filer graph
  274. if(FAILED(hr = pGB.CoCreateInstance(CLSID_FilterGraph))) 
  275. break;
  276. pMC = pGB; pME = pGB; pMS = pGB; pVW = pGB; pBV = pGB;
  277. if(!pMC || !pME || !pMS || !pVW || !pBV) 
  278. break;
  279. if(FAILED(hr = pME->SetNotifyWindow((OAHWND)m_hWnd, WM_GRAPHNOTIFY, 0))) 
  280. break;
  281. // windows media source filter
  282. CComPtr<IBaseFilter> pSrc;
  283. if(FAILED(hr = pSrc.CoCreateInstance(CLSID_NetShowSource))
  284. || FAILED(hr = pGB->AddFilter(pSrc, CStringW(src)))
  285. || FAILED(hr = CComQIPtr<IFileSourceFilter>(pSrc)->Load(CStringW(src), NULL)))
  286. break;
  287. // matroska muxer
  288. CComPtr<IBaseFilter> pMux;
  289. if(FAILED(hr = pMux.CoCreateInstance(__uuidof(CMatroskaMuxerFilter)))
  290. && !(pMux = new CMatroskaMuxerFilter(NULL, NULL))
  291. || FAILED(hr = pGB->AddFilter(pMux, L"Matroska Muxer")))
  292. break;
  293. BeginEnumPins(pSrc, pEP, pPin)
  294. if(FAILED(hr = pGB->Connect(pPin, GetFirstDisconnectedPin(pMux, PINDIR_INPUT)))) 
  295. break;
  296. EndEnumPins
  297. if(FAILED(hr))
  298. break;
  299. // file writer
  300. CComPtr<IBaseFilter> pFW;
  301. if(FAILED(hr = pFW.CoCreateInstance(CLSID_FileWriter))
  302. || FAILED(hr = pGB->AddFilter(pFW, CStringW(m_dst)))
  303. || FAILED(hr = CComQIPtr<IFileSinkFilter2>(pFW)->SetFileName(CStringW(m_dst), NULL))
  304. || FAILED(hr = CComQIPtr<IFileSinkFilter2>(pFW)->SetMode(AM_FILE_OVERWRITE))
  305. || FAILED(hr = pGB->Connect(GetFirstDisconnectedPin(pMux, PINDIR_OUTPUT), GetFirstDisconnectedPin(pFW, PINDIR_INPUT))))
  306. break;
  307. // insert inf. pin tee
  308. BeginEnumPins(pMux, pEP, pPin)
  309. {
  310. PIN_DIRECTION dir;
  311. CComPtr<IPin> pPinTo;
  312. CMediaType mt;
  313. if(FAILED(pPin->QueryDirection(&dir)) || dir != PINDIR_INPUT
  314. || FAILED(pPin->ConnectedTo(&pPinTo))
  315. || FAILED(pPin->ConnectionMediaType(&mt)))
  316. continue;
  317. // FIXME: the inf pin tee filter makes the video messed up, like when seeking 
  318. // onto a non-keyframe and starting to decode from that point. (audio seems to be ok)
  319. CComPtr<IBaseFilter> pInfPinTee;
  320. if(mt.majortype == MEDIATYPE_Video 
  321. || mt.majortype == MEDIATYPE_Audio)
  322. {
  323. if(FAILED(pGB->Disconnect(pPin))
  324. || FAILED(pGB->Disconnect(pPinTo))
  325. || FAILED(pInfPinTee.CoCreateInstance(CLSID_InfTee))
  326. || FAILED(pGB->AddFilter(pInfPinTee, L"Infinite Pin Tee")))
  327. continue;
  328. if(FAILED(pGB->Connect(pPinTo, GetFirstDisconnectedPin(pInfPinTee, PINDIR_INPUT)))
  329. || FAILED(pGB->Connect(GetFirstDisconnectedPin(pInfPinTee, PINDIR_OUTPUT), pPin)))
  330. {
  331. pGB->RemoveFilter(pInfPinTee);
  332. pGB->ConnectDirect(pPinTo, pPin, NULL);
  333. continue;
  334. }
  335. }
  336. pPin = GetFirstDisconnectedPin(pInfPinTee, PINDIR_OUTPUT);
  337. CComPtr<IBaseFilter> pRenderer;
  338. if(mt.majortype == MEDIATYPE_Video)
  339. {
  340. if(SUCCEEDED(pRenderer.CoCreateInstance(CLSID_VideoRendererDefault))
  341. || SUCCEEDED(pRenderer.CoCreateInstance(CLSID_VideoRenderer)))
  342. pPinTo = ::GetFirstDisconnectedPin(pRenderer, PINDIR_INPUT);
  343. }
  344. else if(mt.majortype == MEDIATYPE_Audio)
  345. {
  346. if(SUCCEEDED(pRenderer.CoCreateInstance(CLSID_DSoundRender)))
  347. pPinTo = ::GetFirstDisconnectedPin(pRenderer, PINDIR_INPUT);
  348. }
  349. if(pPin && pPinTo && pRenderer)
  350. {
  351. if(SUCCEEDED(pGB->AddFilter(pRenderer, L"Renderer"))
  352. && FAILED(pGB->Connect(pPin, pPinTo)))
  353. pGB->RemoveFilter(pRenderer);
  354. }
  355. }
  356. EndEnumPins
  357. // setup video window
  358. if(SUCCEEDED(pVW->put_Owner((OAHWND)m_video.m_hWnd))
  359. && SUCCEEDED(pVW->put_WindowStyle(WS_CHILD|WS_CLIPSIBLINGS|WS_CLIPCHILDREN))
  360. && SUCCEEDED(pVW->put_MessageDrain((OAHWND)m_hWnd)))
  361. {
  362. SetVideoRect();
  363. }
  364. // timer for polling the position
  365. SetTimer(1, 500, NULL);
  366. // go!
  367. if(FAILED(hr = pMC->Run()))
  368. break;
  369. hr = S_OK;
  370. }
  371. while(false);
  372. if(FAILED(hr)) OnRecord();
  373. }
  374. else
  375. {
  376. if(pMC) pMC->Stop();
  377. pMC.Release(); pME.Release(); pMS.Release();
  378. pVW.Release(); pBV.Release();
  379. pGB.Release();
  380. m_fRecording = false;
  381. SetWindowText(ResStr(IDS_TITLE));
  382. }
  383. }
  384. void Casf2mkvDlg::OnUpdateRecord(CCmdUI* pCmdUI)
  385. {
  386. CString url;
  387. m_combo.GetWindowText(url);
  388. url.Trim();
  389. pCmdUI->Enable(!url.IsEmpty());
  390. pCmdUI->SetText(ResStr(!m_fRecording ? IDS_RECORD : IDS_STOP));
  391. }
  392. void Casf2mkvDlg::OnUpdateFileName(CCmdUI* pCmdUI)
  393. {
  394. pCmdUI->Enable(!m_fRecording);
  395. }
  396. void Casf2mkvDlg::OnUpdateSettings(CCmdUI* pCmdUI)
  397. {
  398. pCmdUI->Enable(!m_fRecording);
  399. }
  400. void Casf2mkvDlg::OnSize(UINT nType, int cx, int cy)
  401. {
  402. CResizableDialog::OnSize(nType, cx, cy);
  403. SetVideoRect();
  404. }
  405. void Casf2mkvDlg::OnTimer(UINT nIDEvent)
  406. {
  407. if(nIDEvent == 1)
  408. {
  409. if(pMS)
  410. {
  411. REFERENCE_TIME rtPos = 0, rtDur = 0;
  412. pMS->GetCurrentPosition(&rtPos);
  413. pMS->GetDuration(&rtDur);
  414. CString title;
  415. if(rtDur > 0) title.Format(_T("%s (progress: %I64d%%)"), ResStr(IDS_TITLE), 100i64 * rtPos / rtDur);
  416. else title = ResStr(IDS_TITLE) + _T(" (live)");
  417. BeginEnumFilters(pGB, pEF, pBF)
  418. {
  419. if(CComQIPtr<IAMNetworkStatus, &IID_IAMNetworkStatus> pAMNS = pBF)
  420. {
  421. long BufferingProgress = 0;
  422. if(SUCCEEDED(pAMNS->get_BufferingProgress(&BufferingProgress)) && BufferingProgress > 0)
  423. {
  424. CString str;
  425. str.Format(_T(" (buffer: %d%%)"), BufferingProgress);
  426. title += str;
  427. }
  428. break;
  429. }
  430. }
  431. EndEnumFilters
  432. SetWindowText(title);
  433. }
  434. }
  435. CResizableDialog::OnTimer(nIDEvent);
  436. }
  437. void Casf2mkvDlg::OnBnClickedButton2()
  438. {
  439. CComPtr<IBaseFilter> pBF;
  440. pBF.CoCreateInstance(CLSID_NetShowSource);
  441. if(pBF) ShowPPage(pBF, m_hWnd);
  442. }
  443. LRESULT Casf2mkvDlg::OnUrlOpen(WPARAM wParam, LPARAM lParam)
  444. {
  445. m_combo.SetWindowText(CString((char*)lParam));
  446. return 0;
  447. }
  448. //////////////////
  449. Casf2mkvDlg::CRecentFileAndURLList::CRecentFileAndURLList(UINT nStart, LPCTSTR lpszSection,
  450. LPCTSTR lpszEntryFormat, int nSize,
  451. int nMaxDispLen) 
  452. : CRecentFileList(nStart, lpszSection, lpszEntryFormat, nSize, nMaxDispLen)
  453. {
  454. }
  455. //#include <afximpl.h>
  456. extern BOOL AFXAPI AfxFullPath(LPTSTR lpszPathOut, LPCTSTR lpszFileIn);
  457. extern BOOL AFXAPI AfxComparePath(LPCTSTR lpszPath1, LPCTSTR lpszPath2);
  458. void Casf2mkvDlg::CRecentFileAndURLList::Add(LPCTSTR lpszPathName)
  459. {
  460. ASSERT(m_arrNames != NULL);
  461. ASSERT(lpszPathName != NULL);
  462. ASSERT(AfxIsValidString(lpszPathName));
  463. if(CString(lpszPathName).MakeLower().Find(_T("@device:")) >= 0)
  464. return;
  465. bool fURL = (CString(lpszPathName).Find(_T("://")) >= 0);
  466. // fully qualify the path name
  467. TCHAR szTemp[_MAX_PATH];
  468. if(fURL) _tcscpy(szTemp, lpszPathName);
  469. else AfxFullPath(szTemp, lpszPathName);
  470. // update the MRU list, if an existing MRU string matches file name
  471. int iMRU;
  472. for (iMRU = 0; iMRU < m_nSize-1; iMRU++)
  473. {
  474. if((fURL && !_tcscmp(m_arrNames[iMRU], szTemp))
  475. || AfxComparePath(m_arrNames[iMRU], szTemp))
  476. break;      // iMRU will point to matching entry
  477. }
  478. // move MRU strings before this one down
  479. for (; iMRU > 0; iMRU--)
  480. {
  481. ASSERT(iMRU > 0);
  482. ASSERT(iMRU < m_nSize);
  483. m_arrNames[iMRU] = m_arrNames[iMRU-1];
  484. }
  485. // place this one at the beginning
  486. m_arrNames[0] = szTemp;
  487. }