00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "stdafx.h"
00026 #include "asf2mkv.h"
00027 #include "asf2mkvDlg.h"
00028
00029 #ifdef _DEBUG
00030 #define new DEBUG_NEW
00031 #endif
00032
00033 #include <initguid.h>
00034 #include ".\asf2mkvdlg.h"
00035
00036
00037 DEFINE_GUID(CLSID_NetShowSource,
00038 0x6b6d0800, 0x9ada, 0x11d0, 0xa5, 0x20, 0x0, 0xa0, 0xd1, 0x1, 0x29, 0xc0);
00039
00040
00041
00042 class CAboutDlg : public CDialog
00043 {
00044 public:
00045 CAboutDlg();
00046
00047
00048 enum { IDD = IDD_ABOUTBOX };
00049
00050 protected:
00051 virtual void DoDataExchange(CDataExchange* pDX);
00052
00053
00054 protected:
00055 DECLARE_MESSAGE_MAP()
00056 };
00057
00058 CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
00059 {
00060 }
00061
00062 void CAboutDlg::DoDataExchange(CDataExchange* pDX)
00063 {
00064 CDialog::DoDataExchange(pDX);
00065 }
00066
00067 BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
00068 END_MESSAGE_MAP()
00069
00070
00071
00072 BEGIN_MESSAGE_MAP(CUrlDropTarget, COleDropTarget)
00073 END_MESSAGE_MAP()
00074
00075 DROPEFFECT CUrlDropTarget::OnDragEnter(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point)
00076 {
00077 return DROPEFFECT_NONE;
00078 }
00079
00080 DROPEFFECT CUrlDropTarget::OnDragOver(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point)
00081 {
00082 UINT CF_URL = RegisterClipboardFormat(_T("UniformResourceLocator"));
00083 return pDataObject->IsDataAvailable(CF_URL) ? DROPEFFECT_COPY : DROPEFFECT_NONE;
00084 }
00085
00086 BOOL CUrlDropTarget::OnDrop(CWnd* pWnd, COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point)
00087 {
00088 UINT CF_URL = RegisterClipboardFormat(_T("UniformResourceLocator"));
00089
00090 BOOL bResult = FALSE;
00091
00092 if(pDataObject->IsDataAvailable(CF_URL))
00093 {
00094 FORMATETC fmt = {CF_URL, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
00095 if(HGLOBAL hGlobal = pDataObject->GetGlobalData(CF_URL, &fmt))
00096 {
00097 LPCSTR pText = (LPCSTR)GlobalLock(hGlobal);
00098 if(AfxIsValidString(pText))
00099 {
00100 AfxGetMainWnd()->SendMessage(WM_OPENURL, 0, (LPARAM)pText);
00101 GlobalUnlock(hGlobal);
00102 bResult = TRUE;
00103 }
00104 }
00105 }
00106
00107 return bResult;
00108 }
00109
00110 DROPEFFECT CUrlDropTarget::OnDropEx(CWnd* pWnd, COleDataObject* pDataObject, DROPEFFECT dropDefault, DROPEFFECT dropList, CPoint point)
00111 {
00112 return (DROPEFFECT)-1;
00113 }
00114
00115 void CUrlDropTarget::OnDragLeave(CWnd* pWnd)
00116 {
00117 }
00118
00119 DROPEFFECT CUrlDropTarget::OnDragScroll(CWnd* pWnd, DWORD dwKeyState, CPoint point)
00120 {
00121 return DROPEFFECT_NONE;
00122 }
00123
00124
00125
00126 #define WM_GRAPHNOTIFY (WM_APP+1)
00127
00128 Casf2mkvDlg::Casf2mkvDlg(CWnd* pParent )
00129 : CResizableDialog(Casf2mkvDlg::IDD, pParent)
00130 , m_fRecording(false)
00131 , m_mru(0, _T("MRU"), _T("file%d"), 20, 10)
00132 {
00133 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
00134 }
00135
00136 void Casf2mkvDlg::DoDataExchange(CDataExchange* pDX)
00137 {
00138 __super::DoDataExchange(pDX);
00139 DDX_Control(pDX, IDC_COMBO1, m_combo);
00140 DDX_Control(pDX, IDC_STATIC1, m_video);
00141 }
00142
00143
00144 void Casf2mkvDlg::SetupCombo()
00145 {
00146 m_combo.ResetContent();
00147 for(int i = 0; i < m_mru.GetSize(); i++)
00148 if(!m_mru[i].IsEmpty())
00149 m_combo.AddString(m_mru[i]);
00150 }
00151
00152 void Casf2mkvDlg::SetVideoRect()
00153 {
00154 if(pVW)
00155 {
00156 CRect r;
00157 m_video.GetWindowRect(r);
00158 r -= r.TopLeft();
00159 pVW->SetWindowPosition(r.left, r.top, r.Width(), r.Height());
00160 }
00161 }
00162
00163 BEGIN_MESSAGE_MAP(Casf2mkvDlg, CResizableDialog)
00164 ON_WM_SYSCOMMAND()
00165 ON_WM_PAINT()
00166 ON_WM_QUERYDRAGICON()
00167 ON_MESSAGE(WM_GRAPHNOTIFY, OnGraphNotify)
00168 ON_BN_CLICKED(IDC_BUTTON1, OnRecord)
00169 ON_UPDATE_COMMAND_UI(IDC_BUTTON1, OnUpdateRecord)
00170 ON_UPDATE_COMMAND_UI(IDC_COMBO1, OnUpdateFileName)
00171 ON_UPDATE_COMMAND_UI(IDC_BUTTON2, OnUpdateSettings)
00172 ON_UPDATE_COMMAND_UI(IDC_CHECK2, OnUpdateSettings)
00173 ON_WM_SIZE()
00174 ON_WM_TIMER()
00175 ON_BN_CLICKED(IDC_BUTTON2, OnBnClickedButton2)
00176 ON_MESSAGE(WM_APP, OnUrlOpen)
00177 END_MESSAGE_MAP()
00178
00179
00180
00181
00182 BOOL Casf2mkvDlg::OnInitDialog()
00183 {
00184 __super::OnInitDialog();
00185
00186
00187
00188
00189 ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
00190 ASSERT(IDM_ABOUTBOX < 0xF000);
00191
00192 CMenu* pSysMenu = GetSystemMenu(FALSE);
00193 if (pSysMenu != NULL)
00194 {
00195 CString strAboutMenu;
00196 strAboutMenu.LoadString(IDS_ABOUTBOX);
00197 if (!strAboutMenu.IsEmpty())
00198 {
00199 pSysMenu->AppendMenu(MF_SEPARATOR);
00200 pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
00201 }
00202 }
00203
00204
00205
00206 SetIcon(m_hIcon, TRUE);
00207 SetIcon(m_hIcon, FALSE);
00208
00209
00210
00211 AddAnchor(IDC_STATIC1, TOP_LEFT, BOTTOM_RIGHT);
00212 AddAnchor(IDC_COMBO1, BOTTOM_LEFT, BOTTOM_RIGHT);
00213 AddAnchor(IDC_BUTTON1, BOTTOM_RIGHT);
00214 AddAnchor(IDC_BUTTON2, BOTTOM_RIGHT);
00215
00216 m_mru.ReadList();
00217 SetupCombo();
00218
00219 m_video.ModifyStyle(0, WS_CLIPCHILDREN);
00220
00221 SetWindowText(ResStr(IDS_TITLE));
00222
00223 m_urlDropTarget.Register(this);
00224
00225 return TRUE;
00226 }
00227
00228 BOOL Casf2mkvDlg::DestroyWindow()
00229 {
00230 m_urlDropTarget.Revoke();
00231
00232 return __super::DestroyWindow();
00233 }
00234
00235 void Casf2mkvDlg::OnSysCommand(UINT nID, LPARAM lParam)
00236 {
00237 if ((nID & 0xFFF0) == IDM_ABOUTBOX)
00238 {
00239 CAboutDlg dlgAbout;
00240 dlgAbout.DoModal();
00241 }
00242 else
00243 {
00244 __super::OnSysCommand(nID, lParam);
00245 }
00246 }
00247
00248
00249
00250
00251
00252 void Casf2mkvDlg::OnPaint()
00253 {
00254 if (IsIconic())
00255 {
00256 CPaintDC dc(this);
00257
00258 SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
00259
00260
00261 int cxIcon = GetSystemMetrics(SM_CXICON);
00262 int cyIcon = GetSystemMetrics(SM_CYICON);
00263 CRect rect;
00264 GetClientRect(&rect);
00265 int x = (rect.Width() - cxIcon + 1) / 2;
00266 int y = (rect.Height() - cyIcon + 1) / 2;
00267
00268
00269 dc.DrawIcon(x, y, m_hIcon);
00270 }
00271 else
00272 {
00273 __super::OnPaint();
00274 }
00275 }
00276
00277
00278
00279 HCURSOR Casf2mkvDlg::OnQueryDragIcon()
00280 {
00281 return static_cast<HCURSOR>(m_hIcon);
00282 }
00283
00284
00285 LRESULT Casf2mkvDlg::OnGraphNotify(WPARAM wParam, LPARAM lParam)
00286 {
00287 HRESULT hr = S_OK;
00288
00289 LONG evCode, evParam1, evParam2;
00290 while(pME && SUCCEEDED(pME->GetEvent(&evCode, (LONG_PTR*)&evParam1, (LONG_PTR*)&evParam2, 0)))
00291 {
00292 hr = pME->FreeEventParams(evCode, evParam1, evParam2);
00293
00294 if(EC_COMPLETE == evCode)
00295 {
00296 if(m_fRecording)
00297 {
00298 OnRecord();
00299 break;
00300 }
00301 }
00302 }
00303
00304 return hr;
00305 }
00306
00307 void Casf2mkvDlg::OnRecord()
00308 {
00309 UpdateData();
00310
00311 HRESULT hr;
00312
00313 if(!m_fRecording)
00314 {
00315 m_fRecording = true;
00316
00317 UpdateDialogControls(this, FALSE);
00318
00319 hr = E_FAIL;
00320
00321 do
00322 {
00323
00324
00325 CString src;
00326 m_combo.GetWindowText(src);
00327
00328 CFileDialog fd(
00329 FALSE, _T("mkv"), m_dst,
00330 OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_EXPLORER|OFN_ENABLESIZING,
00331 _T("Matroska file (*.mkv;*.mka)|*.mkv;*.mka||"),
00332 this);
00333 if(fd.DoModal() != IDOK) break;
00334 m_dst = fd.GetPathName();
00335
00336 m_mru.Add(src);
00337 m_mru.WriteList();
00338 SetupCombo();
00339 m_combo.SetWindowText(src);
00340
00341 if(src.Trim().IsEmpty() || m_dst.Trim().IsEmpty())
00342 break;
00343
00344
00345
00346 if(FAILED(hr = pGB.CoCreateInstance(CLSID_FilterGraph)))
00347 break;
00348
00349 pMC = pGB; pME = pGB; pMS = pGB; pVW = pGB; pBV = pGB;
00350 if(!pMC || !pME || !pMS || !pVW || !pBV)
00351 break;
00352
00353 if(FAILED(hr = pME->SetNotifyWindow((OAHWND)m_hWnd, WM_GRAPHNOTIFY, 0)))
00354 break;
00355
00356
00357
00358 CComPtr<IBaseFilter> pSrc;
00359 if(FAILED(hr = pSrc.CoCreateInstance(CLSID_NetShowSource))
00360 || FAILED(hr = pGB->AddFilter(pSrc, CStringW(src)))
00361 || FAILED(hr = CComQIPtr<IFileSourceFilter>(pSrc)->Load(CStringW(src), NULL)))
00362 break;
00363
00364
00365
00366 CComPtr<IBaseFilter> pMux;
00367 if(FAILED(hr = pMux.CoCreateInstance(__uuidof(CMatroskaMuxerFilter)))
00368 && !(pMux = new CMatroskaMuxerFilter(NULL, NULL))
00369 || FAILED(hr = pGB->AddFilter(pMux, L"Matroska Muxer")))
00370 break;
00371
00372 BeginEnumPins(pSrc, pEP, pPin)
00373 if(FAILED(hr = pGB->Connect(pPin, GetFirstDisconnectedPin(pMux, PINDIR_INPUT))))
00374 break;
00375 EndEnumPins
00376
00377 if(FAILED(hr))
00378 break;
00379
00380
00381
00382 CComPtr<IBaseFilter> pFW;
00383 if(FAILED(hr = pFW.CoCreateInstance(CLSID_FileWriter))
00384 || FAILED(hr = pGB->AddFilter(pFW, CStringW(m_dst)))
00385 || FAILED(hr = CComQIPtr<IFileSinkFilter2>(pFW)->SetFileName(CStringW(m_dst), NULL))
00386 || FAILED(hr = CComQIPtr<IFileSinkFilter2>(pFW)->SetMode(AM_FILE_OVERWRITE))
00387 || FAILED(hr = pGB->Connect(GetFirstDisconnectedPin(pMux, PINDIR_OUTPUT), GetFirstDisconnectedPin(pFW, PINDIR_INPUT))))
00388 break;
00389
00390
00391
00392 BeginEnumPins(pMux, pEP, pPin)
00393 {
00394 PIN_DIRECTION dir;
00395 CComPtr<IPin> pPinTo;
00396 CMediaType mt;
00397 if(FAILED(pPin->QueryDirection(&dir)) || dir != PINDIR_INPUT
00398 || FAILED(pPin->ConnectedTo(&pPinTo))
00399 || FAILED(pPin->ConnectionMediaType(&mt)))
00400 continue;
00401
00402
00403
00404
00405 CComPtr<IBaseFilter> pInfPinTee;
00406 if(mt.majortype == MEDIATYPE_Video
00407 || mt.majortype == MEDIATYPE_Audio)
00408 {
00409 if(FAILED(pGB->Disconnect(pPin))
00410 || FAILED(pGB->Disconnect(pPinTo))
00411 || FAILED(pInfPinTee.CoCreateInstance(CLSID_InfTee))
00412 || FAILED(pGB->AddFilter(pInfPinTee, L"Infinite Pin Tee")))
00413 continue;
00414
00415 if(FAILED(pGB->Connect(pPinTo, GetFirstDisconnectedPin(pInfPinTee, PINDIR_INPUT)))
00416 || FAILED(pGB->Connect(GetFirstDisconnectedPin(pInfPinTee, PINDIR_OUTPUT), pPin)))
00417 {
00418 pGB->RemoveFilter(pInfPinTee);
00419 pGB->ConnectDirect(pPinTo, pPin, NULL);
00420 continue;
00421 }
00422 }
00423
00424 pPin = GetFirstDisconnectedPin(pInfPinTee, PINDIR_OUTPUT);
00425
00426 CComPtr<IBaseFilter> pRenderer;
00427
00428 if(mt.majortype == MEDIATYPE_Video)
00429 {
00430 if(SUCCEEDED(pRenderer.CoCreateInstance(CLSID_VideoRendererDefault))
00431 || SUCCEEDED(pRenderer.CoCreateInstance(CLSID_VideoRenderer)))
00432 pPinTo = ::GetFirstDisconnectedPin(pRenderer, PINDIR_INPUT);
00433 }
00434 else if(mt.majortype == MEDIATYPE_Audio)
00435 {
00436 if(SUCCEEDED(pRenderer.CoCreateInstance(CLSID_DSoundRender)))
00437 pPinTo = ::GetFirstDisconnectedPin(pRenderer, PINDIR_INPUT);
00438 }
00439
00440 if(pPin && pPinTo && pRenderer)
00441 {
00442 if(SUCCEEDED(pGB->AddFilter(pRenderer, L"Renderer"))
00443 && FAILED(pGB->Connect(pPin, pPinTo)))
00444 pGB->RemoveFilter(pRenderer);
00445 }
00446 }
00447 EndEnumPins
00448
00449
00450
00451 if(SUCCEEDED(pVW->put_Owner((OAHWND)m_video.m_hWnd))
00452 && SUCCEEDED(pVW->put_WindowStyle(WS_CHILD|WS_CLIPSIBLINGS|WS_CLIPCHILDREN))
00453 && SUCCEEDED(pVW->put_MessageDrain((OAHWND)m_hWnd)))
00454 {
00455 SetVideoRect();
00456 }
00457
00458
00459
00460 SetTimer(1, 500, NULL);
00461
00462
00463
00464 if(FAILED(hr = pMC->Run()))
00465 break;
00466
00467 hr = S_OK;
00468 }
00469 while(false);
00470
00471 if(FAILED(hr)) OnRecord();
00472 }
00473 else
00474 {
00475 if(pMC) pMC->Stop();
00476
00477 pMC.Release(); pME.Release(); pMS.Release();
00478 pVW.Release(); pBV.Release();
00479 pGB.Release();
00480
00481 m_fRecording = false;
00482
00483 SetWindowText(ResStr(IDS_TITLE));
00484 }
00485 }
00486
00487 void Casf2mkvDlg::OnUpdateRecord(CCmdUI* pCmdUI)
00488 {
00489 CString url;
00490 m_combo.GetWindowText(url);
00491 url.Trim();
00492 pCmdUI->Enable(!url.IsEmpty());
00493 pCmdUI->SetText(ResStr(!m_fRecording ? IDS_RECORD : IDS_STOP));
00494 }
00495
00496 void Casf2mkvDlg::OnUpdateFileName(CCmdUI* pCmdUI)
00497 {
00498 pCmdUI->Enable(!m_fRecording);
00499 }
00500
00501 void Casf2mkvDlg::OnUpdateSettings(CCmdUI* pCmdUI)
00502 {
00503 pCmdUI->Enable(!m_fRecording);
00504 }
00505
00506 void Casf2mkvDlg::OnSize(UINT nType, int cx, int cy)
00507 {
00508 CResizableDialog::OnSize(nType, cx, cy);
00509
00510 SetVideoRect();
00511 }
00512
00513 void Casf2mkvDlg::OnTimer(UINT nIDEvent)
00514 {
00515 if(nIDEvent == 1)
00516 {
00517 if(pMS)
00518 {
00519 REFERENCE_TIME rtPos = 0, rtDur = 0;
00520 pMS->GetCurrentPosition(&rtPos);
00521 pMS->GetDuration(&rtDur);
00522
00523 CString title;
00524 if(rtDur > 0) title.Format(_T("%s (progress: %I64d%%)"), ResStr(IDS_TITLE), 100i64 * rtPos / rtDur);
00525 else title = ResStr(IDS_TITLE) + _T(" (live)");
00526
00527 BeginEnumFilters(pGB, pEF, pBF)
00528 {
00529 if(CComQIPtr<IAMNetworkStatus, &IID_IAMNetworkStatus> pAMNS = pBF)
00530 {
00531 long BufferingProgress = 0;
00532 if(SUCCEEDED(pAMNS->get_BufferingProgress(&BufferingProgress)) && BufferingProgress > 0)
00533 {
00534 CString str;
00535 str.Format(_T(" (buffer: %d%%)"), BufferingProgress);
00536 title += str;
00537 }
00538 break;
00539 }
00540 }
00541 EndEnumFilters
00542
00543 SetWindowText(title);
00544 }
00545 }
00546
00547 CResizableDialog::OnTimer(nIDEvent);
00548 }
00549
00550 void Casf2mkvDlg::OnBnClickedButton2()
00551 {
00552 CComPtr<IBaseFilter> pBF;
00553 pBF.CoCreateInstance(CLSID_NetShowSource);
00554 if(pBF) ShowPPage(pBF, m_hWnd);
00555 }
00556
00557 LRESULT Casf2mkvDlg::OnUrlOpen(WPARAM wParam, LPARAM lParam)
00558 {
00559 m_combo.SetWindowText(CString((char*)lParam));
00560 return 0;
00561 }
00562
00564
00565 Casf2mkvDlg::CRecentFileAndURLList::CRecentFileAndURLList(UINT nStart, LPCTSTR lpszSection,
00566 LPCTSTR lpszEntryFormat, int nSize,
00567 int nMaxDispLen)
00568 : CRecentFileList(nStart, lpszSection, lpszEntryFormat, nSize, nMaxDispLen)
00569 {
00570 }
00571
00572
00573 extern BOOL AFXAPI AfxFullPath(LPTSTR lpszPathOut, LPCTSTR lpszFileIn);
00574 extern BOOL AFXAPI AfxComparePath(LPCTSTR lpszPath1, LPCTSTR lpszPath2);
00575
00576 void Casf2mkvDlg::CRecentFileAndURLList::Add(LPCTSTR lpszPathName)
00577 {
00578 ASSERT(m_arrNames != NULL);
00579 ASSERT(lpszPathName != NULL);
00580 ASSERT(AfxIsValidString(lpszPathName));
00581
00582 if(CString(lpszPathName).MakeLower().Find(_T("@device:")) >= 0)
00583 return;
00584
00585 bool fURL = (CString(lpszPathName).Find(_T("://")) >= 0);
00586
00587
00588 TCHAR szTemp[_MAX_PATH];
00589 if(fURL) _tcscpy(szTemp, lpszPathName);
00590 else AfxFullPath(szTemp, lpszPathName);
00591
00592
00593 int iMRU;
00594 for (iMRU = 0; iMRU < m_nSize-1; iMRU++)
00595 {
00596 if((fURL && !_tcscmp(m_arrNames[iMRU], szTemp))
00597 || AfxComparePath(m_arrNames[iMRU], szTemp))
00598 break;
00599 }
00600
00601 for (; iMRU > 0; iMRU--)
00602 {
00603 ASSERT(iMRU > 0);
00604 ASSERT(iMRU < m_nSize);
00605 m_arrNames[iMRU] = m_arrNames[iMRU-1];
00606 }
00607
00608 m_arrNames[0] = szTemp;
00609 }