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

多媒体编程

开发平台:

Visual C++

  1. pAS->SetAudioTimeShift(rtShift);
  2. CString str;
  3. str.Format(_T("Audio Delay: %I64dms"), rtShift/10000);
  4. SendStatusMessage(str, 3000);
  5. }
  6. }
  7. void CMainFrame::OnUpdatePlayChangeAudDelay(CCmdUI* pCmdUI)
  8. {
  9. pCmdUI->Enable(pGB && !!FindFilter(__uuidof(CAudioSwitcherFilter), pGB));
  10. }
  11. #include "ComPropertySheet.h"
  12. #include ".mainfrm.h"
  13. void CMainFrame::OnPlayFilters(UINT nID)
  14. {
  15. // ShowPPage(m_spparray[nID - ID_FILTERS_SUBITEM_START], m_hWnd);
  16. CComPtr<ISpecifyPropertyPages> pSPP = m_spparray[nID - ID_FILTERS_SUBITEM_START];
  17. CComPropertySheet ps(_T("Properties"), this);
  18. ps.AddPages(pSPP);
  19. ps.DoModal();
  20. OpenSetupStatusBar();
  21. }
  22. void CMainFrame::OnUpdatePlayFilters(CCmdUI* pCmdUI)
  23. {
  24. pCmdUI->Enable(!m_fCapturing);
  25. }
  26. void CMainFrame::OnPlayShaders(UINT nID)
  27. {
  28. if(nID == ID_SHADERS_START)
  29. {
  30. CShaderEditorDlg(m_shaderlabel, m_pCAP, this).DoModal();
  31. }
  32. else if(nID == ID_SHADERS_START+1)
  33. {
  34. m_pCAP->SetPixelShader(NULL, NULL);
  35. m_shaderlabel.Empty();
  36. }
  37. else if(nID >= ID_SHADERS_START+2)
  38. {
  39. nID -= ID_SHADERS_START+2;
  40. CString str;
  41. str.Format(_T("%d"), nID);
  42. CList<CString> sl;
  43. Explode(AfxGetApp()->GetProfileString(_T("Shaders"), str), sl, '|', 3);
  44. if(sl.GetCount() != 3) {AfxMessageBox(_T("Invalid shader data"), S_OK); return;}
  45. CString label = sl.RemoveHead();
  46. CStringA target = CStringA(sl.RemoveHead());
  47. CStringA srcdata = CStringA(sl.RemoveHead());
  48. srcdata.Replace("\n", "n");
  49. srcdata.Replace("\t", "t");
  50. HRESULT hr = m_pCAP->SetPixelShader(srcdata, target);
  51. if(FAILED(hr)) AfxMessageBox(_T("Could not load shader."), MB_OK);
  52. else {SendStatusMessage(_T("Shader: ") + label, 3000); m_shaderlabel = label;}
  53. }
  54. }
  55. void CMainFrame::OnUpdatePlayShaders(CCmdUI* pCmdUI)
  56. {
  57. if(pCmdUI->m_nID > ID_SHADERS_START)
  58. {
  59. pCmdUI->Enable(!!m_pCAP);
  60. if(pCmdUI->m_nID == ID_SHADERS_START+1)
  61. {
  62. pCmdUI->SetRadio(m_shaderlabel.IsEmpty());
  63. }
  64. else
  65. {
  66. CString str;
  67. m_shaders.GetMenuString(pCmdUI->m_nID, str, MF_BYCOMMAND);
  68. pCmdUI->SetRadio(str == m_shaderlabel);
  69. }
  70. }
  71. }
  72. void CMainFrame::OnPlayAudio(UINT nID)
  73. {
  74. int i = (int)nID - (1 + ID_AUDIO_SUBITEM_START);
  75. CComQIPtr<IAMStreamSelect> pSS = FindFilter(__uuidof(CAudioSwitcherFilter), pGB);
  76. if(!pSS) pSS = FindFilter(L"{D3CD7858-971A-4838-ACEC-40CA5D529DC8}", pGB);
  77. if(i == -1)
  78. {
  79. ShowOptions(CPPageAudioSwitcher::IDD);
  80. }
  81. else if(i >= 0 && pSS)
  82. {
  83. pSS->Enable(i, AMSTREAMSELECTENABLE_ENABLE);
  84. }
  85. }
  86. void CMainFrame::OnUpdatePlayAudio(CCmdUI* pCmdUI)
  87. {
  88. UINT nID = pCmdUI->m_nID;
  89. int i = (int)nID - (1 + ID_AUDIO_SUBITEM_START);
  90. CComQIPtr<IAMStreamSelect> pSS = FindFilter(__uuidof(CAudioSwitcherFilter), pGB);
  91. if(!pSS) pSS = FindFilter(L"{D3CD7858-971A-4838-ACEC-40CA5D529DC8}", pGB);
  92. /*if(i == -1)
  93. {
  94. // TODO****
  95. }
  96. else*/ if(i >= 0 && pSS)
  97. {
  98. DWORD flags = 0;
  99. if(SUCCEEDED(pSS->Info(i, NULL, &flags, NULL, NULL, NULL, NULL, NULL)))
  100. {
  101. if(flags&AMSTREAMSELECTINFO_EXCLUSIVE) pCmdUI->SetRadio(TRUE);
  102. else if(flags&AMSTREAMSELECTINFO_ENABLED) pCmdUI->SetCheck(TRUE);
  103. else pCmdUI->SetCheck(FALSE);
  104. }
  105. else
  106. {
  107. pCmdUI->Enable(FALSE);
  108. }
  109. }
  110. }
  111. void CMainFrame::OnPlaySubtitles(UINT nID)
  112. {
  113. int i = (int)nID - (4 + ID_SUBTITLES_SUBITEM_START);
  114. if(i == -4)
  115. {
  116. ShowOptions(CPPageSubtitles::IDD);
  117. }
  118. else if(i == -3)
  119. {
  120. int i = m_iSubtitleSel;
  121. POSITION pos = m_pSubStreams.GetHeadPosition();
  122. while(pos && i >= 0)
  123. {
  124. CComPtr<ISubStream> pSubStream = m_pSubStreams.GetNext(pos);
  125. if(i < pSubStream->GetStreamCount())
  126. {
  127. CLSID clsid;
  128. if(FAILED(pSubStream->GetClassID(&clsid)))
  129. continue;
  130. if(clsid == __uuidof(CRenderedTextSubtitle))
  131. {
  132. CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)pSubStream;
  133. CAutoPtrArray<CPPageSubStyle> pages;
  134. CArray<STSStyle*> styles;
  135. POSITION pos = pRTS->m_styles.GetStartPosition();
  136. for(int i = 0; pos; i++)
  137. {
  138. CString key;
  139. void* val;
  140. pRTS->m_styles.GetNextAssoc(pos, key, val);
  141. CAutoPtr<CPPageSubStyle> page(new CPPageSubStyle());
  142. page->InitStyle(key, *(STSStyle*)val);
  143. pages.Add(page);
  144. styles.Add((STSStyle*)val);
  145. }
  146. CPropertySheet dlg(_T("Styles..."), this);
  147. for(int i = 0; i < (int)pages.GetCount(); i++) 
  148. dlg.AddPage(pages[i]);
  149. if(dlg.DoModal() == IDOK)
  150. {
  151. for(int j = 0; j < (int)pages.GetCount(); j++)
  152. pages[j]->GetStyle(*styles[j]);
  153. UpdateSubtitle(false);
  154. }
  155. return;
  156. }
  157. }
  158. i -= pSubStream->GetStreamCount();
  159. }
  160. }
  161. else if(i == -2)
  162. {
  163. ReloadSubtitle();
  164. }
  165. else if(i == -1)
  166. {
  167. m_iSubtitleSel ^= (1<<31);
  168. UpdateSubtitle();
  169. }
  170. else if(i >= 0)
  171. {
  172. m_iSubtitleSel = i;
  173. UpdateSubtitle();
  174. }
  175. }
  176. void CMainFrame::OnUpdatePlaySubtitles(CCmdUI* pCmdUI)
  177. {
  178. UINT nID = pCmdUI->m_nID;
  179. int i = (int)nID - (4 + ID_SUBTITLES_SUBITEM_START);
  180. pCmdUI->Enable(m_pCAP && !m_fAudioOnly);
  181. if(i == -3)
  182. {
  183. pCmdUI->Enable(FALSE);
  184. int i = m_iSubtitleSel;
  185. POSITION pos = m_pSubStreams.GetHeadPosition();
  186. while(pos && i >= 0)
  187. {
  188. CComPtr<ISubStream> pSubStream = m_pSubStreams.GetNext(pos);
  189. if(i < pSubStream->GetStreamCount())
  190. {
  191. CLSID clsid;
  192. if(FAILED(pSubStream->GetClassID(&clsid)))
  193. continue;
  194. if(clsid == __uuidof(CRenderedTextSubtitle))
  195. {
  196. pCmdUI->Enable(TRUE);
  197. break;
  198. }
  199. }
  200. i -= pSubStream->GetStreamCount();
  201. }
  202. }
  203. else if(i == -1)
  204. {
  205. pCmdUI->SetCheck(m_iSubtitleSel >= 0);
  206. }
  207. else if(i >= 0)
  208. {
  209. pCmdUI->SetRadio(i == abs(m_iSubtitleSel));
  210. }
  211. }
  212. void CMainFrame::OnPlayLanguage(UINT nID)
  213. {
  214. nID -= ID_FILTERSTREAMS_SUBITEM_START;
  215. CComPtr<IAMStreamSelect> pAMSS = m_ssarray[nID];
  216. UINT i = nID;
  217. while(i > 0 && pAMSS == m_ssarray[i-1]) i--;
  218. if(FAILED(pAMSS->Enable(nID-i, AMSTREAMSELECTENABLE_ENABLE)))
  219. MessageBeep(-1);
  220. OpenSetupStatusBar();
  221. }
  222. void CMainFrame::OnUpdatePlayLanguage(CCmdUI* pCmdUI)
  223. {
  224. UINT nID = pCmdUI->m_nID;
  225. nID -= ID_FILTERSTREAMS_SUBITEM_START;
  226. CComPtr<IAMStreamSelect> pAMSS = m_ssarray[nID];
  227. UINT i = nID;
  228. while(i > 0 && pAMSS == m_ssarray[i-1]) i--;
  229. DWORD flags = 0;
  230. pAMSS->Info(nID-i, NULL, &flags, NULL, NULL, NULL, NULL, NULL);
  231. if(flags&AMSTREAMSELECTINFO_EXCLUSIVE) pCmdUI->SetRadio(TRUE);
  232. else if(flags&AMSTREAMSELECTINFO_ENABLED) pCmdUI->SetCheck(TRUE);
  233. else pCmdUI->SetCheck(FALSE);
  234. }
  235. void CMainFrame::OnPlayVolume(UINT nID)
  236. {
  237. if(m_iMediaLoadState == MLS_LOADED) 
  238. pBA->put_Volume(m_wndToolBar.Volume);
  239. }
  240. void CMainFrame::OnAfterplayback(UINT nID)
  241. {
  242. AppSettings& s = AfxGetAppSettings();
  243. s.nCLSwitches &= ~CLSW_AFTERPLAYBACK_MASK;
  244. switch(nID)
  245. {
  246. case ID_AFTERPLAYBACK_CLOSE: s.nCLSwitches |= CLSW_CLOSE; break;
  247. case ID_AFTERPLAYBACK_STANDBY: s.nCLSwitches |= CLSW_STANDBY; break;
  248. case ID_AFTERPLAYBACK_HIBERNATE: s.nCLSwitches |= CLSW_HIBERNATE; break;
  249. case ID_AFTERPLAYBACK_SHUTDOWN: s.nCLSwitches |= CLSW_SHUTDOWN; break;
  250. case ID_AFTERPLAYBACK_LOGOFF: s.nCLSwitches |= CLSW_LOGOFF; break;
  251. }
  252. }
  253. void CMainFrame::OnUpdateAfterplayback(CCmdUI* pCmdUI)
  254. {
  255. AppSettings& s = AfxGetAppSettings();
  256. bool fChecked = false;
  257. switch(pCmdUI->m_nID)
  258. {
  259. case ID_AFTERPLAYBACK_CLOSE: fChecked = !!(s.nCLSwitches & CLSW_CLOSE); break;
  260. case ID_AFTERPLAYBACK_STANDBY: fChecked = !!(s.nCLSwitches & CLSW_STANDBY); break;
  261. case ID_AFTERPLAYBACK_HIBERNATE: fChecked = !!(s.nCLSwitches & CLSW_HIBERNATE); break;
  262. case ID_AFTERPLAYBACK_SHUTDOWN: fChecked = !!(s.nCLSwitches & CLSW_SHUTDOWN); break;
  263. case ID_AFTERPLAYBACK_LOGOFF: fChecked = !!(s.nCLSwitches & CLSW_LOGOFF); break;
  264. case ID_AFTERPLAYBACK_DONOTHING: fChecked = !(s.nCLSwitches & CLSW_AFTERPLAYBACK_MASK); break;
  265. }
  266. pCmdUI->SetRadio(fChecked);
  267. }
  268. // navigate
  269. void CMainFrame::OnNavigateSkip(UINT nID)
  270. {
  271. if(m_iPlaybackMode == PM_FILE || m_iPlaybackMode == PM_CAPTURE)
  272. {
  273. if(m_iPlaybackMode == PM_FILE) SetupChapters();
  274. if(DWORD nChapters = m_pCB->ChapGetCount())
  275. {
  276. REFERENCE_TIME rtCur;
  277. pMS->GetCurrentPosition(&rtCur);
  278. REFERENCE_TIME rt = rtCur;
  279. CComBSTR name;
  280. long i;
  281. if(nID == ID_NAVIGATE_SKIPBACK)
  282. {
  283. rt -= 30000000;
  284. i = m_pCB->ChapLookup(&rt, &name);
  285. }
  286. else if(nID == ID_NAVIGATE_SKIPFORWARD)
  287. {
  288. i = m_pCB->ChapLookup(&rt, &name) + 1;
  289. name.Empty();
  290. if(i < nChapters) m_pCB->ChapGet(i, &rt, &name);
  291. }
  292. if(i >= 0 && i < nChapters)
  293. {
  294. SeekTo(rt);
  295. SendStatusMessage(_T("Chapter: ") + CString(name), 3000);
  296. return;
  297. }
  298. }
  299. if(nID == ID_NAVIGATE_SKIPBACK)
  300. {
  301. SendMessage(WM_COMMAND, ID_NAVIGATE_SKIPBACKPLITEM);
  302. }
  303. else if(nID == ID_NAVIGATE_SKIPFORWARD)
  304. {
  305. SendMessage(WM_COMMAND, ID_NAVIGATE_SKIPFORWARDPLITEM);
  306. }
  307. }
  308. else if(m_iPlaybackMode == PM_DVD)
  309. {
  310. m_iSpeedLevel = 0;
  311. if(GetMediaState() != State_Running)
  312. SendMessage(WM_COMMAND, ID_PLAY_PLAY);
  313. ULONG ulNumOfVolumes, ulVolume;
  314. DVD_DISC_SIDE Side;
  315. ULONG ulNumOfTitles = 0;
  316. pDVDI->GetDVDVolumeInfo(&ulNumOfVolumes, &ulVolume, &Side, &ulNumOfTitles);
  317. DVD_PLAYBACK_LOCATION2 Location;
  318. pDVDI->GetCurrentLocation(&Location);
  319. ULONG ulNumOfChapters = 0;
  320. pDVDI->GetNumberOfChapters(Location.TitleNum, &ulNumOfChapters);
  321. if(nID == ID_NAVIGATE_SKIPBACK)
  322. {
  323. if(Location.ChapterNum == 1 && Location.TitleNum > 1)
  324. {
  325. pDVDI->GetNumberOfChapters(Location.TitleNum-1, &ulNumOfChapters);
  326. pDVDC->PlayChapterInTitle(Location.TitleNum-1, ulNumOfChapters, DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
  327. }
  328. else
  329. {
  330. pDVDC->PlayPrevChapter(DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
  331. }
  332. }
  333. else if(nID == ID_NAVIGATE_SKIPFORWARD)
  334. {
  335. if(Location.ChapterNum == ulNumOfChapters && Location.TitleNum < ulNumOfTitles)
  336. {
  337. pDVDC->PlayChapterInTitle(Location.TitleNum+1, 1, DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
  338. }
  339. else
  340. {
  341. pDVDC->PlayNextChapter(DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
  342. }
  343. }
  344. /*
  345.         if(nID == ID_NAVIGATE_SKIPBACK)
  346. pDVDC->PlayPrevChapter(DVD_CMD_FLAG_Block, NULL);
  347. else if(nID == ID_NAVIGATE_SKIPFORWARD)
  348. pDVDC->PlayNextChapter(DVD_CMD_FLAG_Block, NULL);
  349. */
  350. }
  351. }
  352. void CMainFrame::OnUpdateNavigateSkip(CCmdUI* pCmdUI)
  353. {
  354. // moved to the timer callback function, that runs less frequent
  355. // if(m_iPlaybackMode == PM_FILE) SetupChapters();
  356. pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED
  357. && ((m_iPlaybackMode == PM_DVD 
  358. && m_iDVDDomain != DVD_DOMAIN_VideoManagerMenu 
  359. && m_iDVDDomain != DVD_DOMAIN_VideoTitleSetMenu)
  360. || (m_iPlaybackMode == PM_FILE && (m_wndPlaylistBar.GetCount() > 1/*0*/ || m_pCB->ChapGetCount() > 1))
  361. || (m_iPlaybackMode == PM_CAPTURE && !m_fCapturing))); // TODO
  362. }
  363. void CMainFrame::OnNavigateSkipPlaylistItem(UINT nID)
  364. {
  365. if(m_iPlaybackMode == PM_FILE || m_iPlaybackMode == PM_CAPTURE)
  366. {
  367. if(m_wndPlaylistBar.GetCount() == 1)
  368. {
  369. SendMessage(WM_COMMAND, ID_PLAY_STOP); // do not remove this, unless you want a circular call with OnPlayPlay()
  370. SendMessage(WM_COMMAND, ID_PLAY_PLAY);
  371. }
  372. else
  373. {
  374. if(nID == ID_NAVIGATE_SKIPBACKPLITEM)
  375. {
  376. m_wndPlaylistBar.SetPrev();
  377. }
  378. else if(nID == ID_NAVIGATE_SKIPFORWARDPLITEM)
  379. {
  380. m_wndPlaylistBar.SetNext();
  381. }
  382. OpenCurPlaylistItem();
  383. }
  384. }
  385. }
  386. void CMainFrame::OnUpdateNavigateSkipPlaylistItem(CCmdUI* pCmdUI)
  387. {
  388. pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED
  389. && ((m_iPlaybackMode == PM_FILE || m_iPlaybackMode == PM_CAPTURE && !m_fCapturing) && m_wndPlaylistBar.GetCount() > 1/*0*/));
  390. }
  391. void CMainFrame::OnNavigateMenu(UINT nID)
  392. {
  393. nID -= ID_NAVIGATE_TITLEMENU;
  394. if(m_iMediaLoadState != MLS_LOADED || m_iPlaybackMode != PM_DVD)
  395. return;
  396. m_iSpeedLevel = 0;
  397. if(GetMediaState() != State_Running)
  398. SendMessage(WM_COMMAND, ID_PLAY_PLAY);
  399. pDVDC->ShowMenu((DVD_MENU_ID)(nID+2), DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
  400. }
  401. void CMainFrame::OnUpdateNavigateMenu(CCmdUI* pCmdUI)
  402. {
  403. UINT nID = pCmdUI->m_nID - ID_NAVIGATE_TITLEMENU;
  404. ULONG ulUOPs;
  405. if(m_iMediaLoadState != MLS_LOADED || m_iPlaybackMode != PM_DVD 
  406. || FAILED(pDVDI->GetCurrentUOPS(&ulUOPs)))
  407. {
  408. pCmdUI->Enable(FALSE);
  409. return;
  410. }
  411. pCmdUI->Enable(!(ulUOPs & (UOP_FLAG_ShowMenu_Title << nID)));
  412. }
  413. void CMainFrame::OnNavigateAudio(UINT nID)
  414. {
  415. nID -= ID_NAVIGATE_AUDIO_SUBITEM_START;
  416. if(m_iPlaybackMode == PM_FILE)
  417. {
  418. OnNavStreamSelectSubMenu(nID, 1);
  419. }
  420. else if(m_iPlaybackMode == PM_DVD)
  421. {
  422. pDVDC->SelectAudioStream(nID, DVD_CMD_FLAG_Block, NULL);
  423. }
  424. }
  425. void CMainFrame::OnNavigateSubpic(UINT nID)
  426. {
  427. if(m_iPlaybackMode == PM_FILE)
  428. {
  429. OnNavStreamSelectSubMenu(nID - ID_NAVIGATE_SUBP_SUBITEM_START, 2);
  430. }
  431. else if(m_iPlaybackMode == PM_DVD)
  432. {
  433. int i = (int)nID - (1 + ID_NAVIGATE_SUBP_SUBITEM_START);
  434. if(i == -1)
  435. {
  436. ULONG ulStreamsAvailable, ulCurrentStream;
  437. BOOL bIsDisabled;
  438. if(SUCCEEDED(pDVDI->GetCurrentSubpicture(&ulStreamsAvailable, &ulCurrentStream, &bIsDisabled)))
  439. pDVDC->SetSubpictureState(bIsDisabled, DVD_CMD_FLAG_Block, NULL);
  440. }
  441. else
  442. {
  443. pDVDC->SelectSubpictureStream(i, DVD_CMD_FLAG_Block, NULL);
  444. pDVDC->SetSubpictureState(TRUE, DVD_CMD_FLAG_Block, NULL);
  445. }
  446. }
  447. }
  448. void CMainFrame::OnNavigateAngle(UINT nID)
  449. {
  450. nID -= ID_NAVIGATE_ANGLE_SUBITEM_START;
  451. if(m_iPlaybackMode == PM_FILE)
  452. {
  453. OnNavStreamSelectSubMenu(nID, 0);
  454. }
  455. else if(m_iPlaybackMode == PM_DVD)
  456. {
  457. pDVDC->SelectAngle(nID, DVD_CMD_FLAG_Block, NULL);
  458. }
  459. }
  460. void CMainFrame::OnNavigateChapters(UINT nID)
  461. {
  462. nID -= ID_NAVIGATE_CHAP_SUBITEM_START;
  463. if(m_iPlaybackMode == PM_FILE)
  464. {
  465. if((int)nID >= 0 && nID < m_pCB->ChapGetCount())
  466. {
  467. REFERENCE_TIME rt;
  468. CComBSTR name;
  469. if(SUCCEEDED(m_pCB->ChapGet(nID, &rt, &name)))
  470. {
  471. SeekTo(rt);
  472. SendStatusMessage(_T("Chapter: ") + CString(name), 3000);
  473. }
  474. return;
  475. }
  476. nID -= m_pCB->ChapGetCount();
  477. if((int)nID >= 0 && (int)nID < m_wndPlaylistBar.GetCount()
  478. && m_wndPlaylistBar.GetSelIdx() != (int)nID)
  479. {
  480. m_wndPlaylistBar.SetSelIdx(nID);
  481. OpenCurPlaylistItem();
  482. }
  483. }
  484. else if(m_iPlaybackMode == PM_DVD)
  485. {
  486. ULONG ulNumOfVolumes, ulVolume;
  487. DVD_DISC_SIDE Side;
  488. ULONG ulNumOfTitles = 0;
  489. pDVDI->GetDVDVolumeInfo(&ulNumOfVolumes, &ulVolume, &Side, &ulNumOfTitles);
  490. DVD_PLAYBACK_LOCATION2 Location;
  491. pDVDI->GetCurrentLocation(&Location);
  492. ULONG ulNumOfChapters = 0;
  493. pDVDI->GetNumberOfChapters(Location.TitleNum, &ulNumOfChapters);
  494. nID++;
  495. if(nID > 0 && nID <= ulNumOfTitles)
  496. {
  497. pDVDC->PlayTitle(nID, DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL); // sometimes this does not do anything ... 
  498. pDVDC->PlayChapterInTitle(nID, 1, DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL); // ... but this does!
  499. return;
  500. }
  501. nID -= ulNumOfTitles;
  502. if(nID > 0 && nID <= ulNumOfChapters)
  503. {
  504. pDVDC->PlayChapter(nID, DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
  505. return;
  506. }
  507. }
  508. }
  509. void CMainFrame::OnNavigateMenuItem(UINT nID)
  510. {
  511. nID -= ID_NAVIGATE_MENU_LEFT;
  512. if(m_iPlaybackMode == PM_DVD)
  513. {
  514. switch(nID)
  515. {
  516. case 0: pDVDC->SelectRelativeButton(DVD_Relative_Left); break;
  517. case 1: pDVDC->SelectRelativeButton(DVD_Relative_Right); break;
  518. case 2: pDVDC->SelectRelativeButton(DVD_Relative_Upper); break;
  519. case 3: pDVDC->SelectRelativeButton(DVD_Relative_Lower); break;
  520. case 4: pDVDC->ActivateButton(); break;
  521. case 5: pDVDC->ReturnFromSubmenu(DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL); break;
  522. case 6: pDVDC->Resume(DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL); break;
  523. default: break;
  524. }
  525. }
  526. }
  527. void CMainFrame::OnUpdateNavigateMenuItem(CCmdUI* pCmdUI)
  528. {
  529. UINT nID = pCmdUI->m_nID - ID_NAVIGATE_MENU_LEFT;
  530. pCmdUI->Enable(m_iMediaLoadState == MLS_LOADED && m_iPlaybackMode == PM_DVD);
  531. }
  532. // favorites
  533. class CDVDStateStream : public CUnknown, public IStream
  534. {
  535. STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv)
  536. {
  537. return 
  538. QI(IStream)
  539. CUnknown::NonDelegatingQueryInterface(riid, ppv);
  540. }
  541. __int64 m_pos;
  542. public:
  543. CDVDStateStream() : CUnknown(NAME("CDVDStateStream"), NULL) {m_pos = 0;}
  544. DECLARE_IUNKNOWN;
  545. CByteArray m_data;
  546.     // ISequentialStream
  547. STDMETHODIMP Read(void* pv, ULONG cb, ULONG* pcbRead)
  548. {
  549. __int64 cbRead = min(m_data.GetCount() - m_pos, (__int64)cb);
  550. cbRead = max(cbRead, 0);
  551. memcpy(pv, &m_data[(INT_PTR)m_pos], (int)cbRead);
  552. if(pcbRead) *pcbRead = (ULONG)cbRead;
  553. m_pos += cbRead;
  554. return S_OK;
  555. }
  556. STDMETHODIMP Write(const void* pv, ULONG cb, ULONG* pcbWritten)
  557. {
  558. BYTE* p = (BYTE*)pv;
  559. ULONG cbWritten = -1;
  560. while(++cbWritten < cb)
  561. m_data.Add(*p++);
  562. if(pcbWritten) *pcbWritten = cbWritten;
  563. return S_OK;
  564. }
  565. // IStream
  566. STDMETHODIMP Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition) {return E_NOTIMPL;}
  567. STDMETHODIMP SetSize(ULARGE_INTEGER libNewSize) {return E_NOTIMPL;}
  568. STDMETHODIMP CopyTo(IStream* pstm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten) {return E_NOTIMPL;}
  569. STDMETHODIMP Commit(DWORD grfCommitFlags) {return E_NOTIMPL;}
  570. STDMETHODIMP Revert() {return E_NOTIMPL;}
  571. STDMETHODIMP LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {return E_NOTIMPL;}
  572. STDMETHODIMP UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {return E_NOTIMPL;}
  573. STDMETHODIMP Stat(STATSTG* pstatstg, DWORD grfStatFlag) {return E_NOTIMPL;}
  574. STDMETHODIMP Clone(IStream** ppstm) {return E_NOTIMPL;}
  575. };
  576. void CMainFrame::OnFavoritesAdd()
  577. {
  578. AppSettings& s = AfxGetAppSettings();
  579. if(m_iPlaybackMode == PM_FILE)
  580. {
  581. CString fn =  m_wndPlaylistBar.GetCur();
  582. if(fn.IsEmpty()) return;
  583. CString desc = fn;
  584. desc.Replace('\', '/');
  585. int i = desc.Find(_T("://")), j = desc.Find(_T("?")), k = desc.ReverseFind('/');
  586. if(i >= 0) desc = j >= 0 ? desc.Left(j) : desc;
  587. else if(k >= 0) desc = desc.Mid(k+1);
  588. CFavoriteAddDlg dlg(desc, fn);
  589. if(dlg.DoModal() != IDOK) return;
  590. CString str = dlg.m_name;
  591. str.Remove(';');
  592. CString pos(_T("0"));
  593. if(dlg.m_fRememberPos)
  594. pos.Format(_T("%I64d"), GetPos());
  595. str += ';';
  596. str += pos;
  597. CPlaylistItem pli;
  598. if(m_wndPlaylistBar.GetCur(pli))
  599. {
  600. POSITION pos = pli.m_fns.GetHeadPosition();
  601. while(pos) str += _T(";") + pli.m_fns.GetNext(pos);
  602. }
  603. s.AddFav(FAV_FILE, str);
  604. }
  605. else if(m_iPlaybackMode == PM_DVD)
  606. {
  607. WCHAR path[MAX_PATH];
  608. ULONG len = 0;
  609. pDVDI->GetDVDDirectory(path, MAX_PATH, &len);
  610. CString fn = path;
  611. fn.TrimRight(_T("/\"));
  612. DVD_PLAYBACK_LOCATION2 Location;
  613. pDVDI->GetCurrentLocation(&Location);
  614. CString desc;
  615. desc.Format(_T("%s - T%02d C%02d - %02d:%02d:%02d"), fn, Location.TitleNum, Location.ChapterNum, 
  616. Location.TimeCode.bHours, Location.TimeCode.bMinutes, Location.TimeCode.bSeconds);
  617. CFavoriteAddDlg dlg(fn, desc);
  618. if(dlg.DoModal() != IDOK) return;
  619. CString str = dlg.m_name;
  620. str.Remove(';');
  621. CString pos(_T("0"));
  622. if(dlg.m_fRememberPos)
  623. {
  624. CDVDStateStream stream;
  625. stream.AddRef();
  626. CComPtr<IDvdState> pStateData;
  627. CComQIPtr<IPersistStream> pPersistStream;
  628. if(SUCCEEDED(pDVDI->GetState(&pStateData))
  629. && (pPersistStream = pStateData)
  630. && SUCCEEDED(OleSaveToStream(pPersistStream, (IStream*)&stream)))
  631. {
  632. pos = BinToString(stream.m_data.GetData(), stream.m_data.GetCount());
  633. }
  634. }
  635. str += ';';
  636. str += pos;
  637. str += ';';
  638. str += fn;
  639. s.AddFav(FAV_DVD, str);
  640. }
  641. else if(m_iPlaybackMode == PM_CAPTURE)
  642. {
  643. // TODO
  644. }
  645. }
  646. void CMainFrame::OnUpdateFavoritesAdd(CCmdUI* pCmdUI)
  647. {
  648. pCmdUI->Enable(m_iPlaybackMode == PM_FILE || m_iPlaybackMode == PM_DVD);
  649. }
  650. void CMainFrame::OnFavoritesOrganize()
  651. {
  652. CFavoriteOrganizeDlg dlg;
  653. dlg.DoModal();
  654. }
  655. void CMainFrame::OnUpdateFavoritesOrganize(CCmdUI* pCmdUI)
  656. {
  657. // TODO: Add your command update UI handler code here
  658. }
  659. void CMainFrame::OnFavoritesFile(UINT nID)
  660. {
  661. nID -= ID_FAVORITES_FILE_START;
  662. CList<CString> sl;
  663. AfxGetAppSettings().GetFav(FAV_FILE, sl);
  664. if(POSITION pos = sl.FindIndex(nID))
  665. {
  666. CList<CString> fns;
  667. REFERENCE_TIME rtStart = 0;
  668. int i = 0, j = 0;
  669. for(CString s1 = sl.GetAt(pos), s2 = s1.Tokenize(_T(";"), i); 
  670. !s2.IsEmpty(); 
  671. s2 = s1.Tokenize(_T(";"), i), j++)
  672. {
  673. if(j == 0) ; // desc
  674. else if(j == 1) _stscanf(s2, _T("%I64d"), &rtStart); // pos
  675. else fns.AddTail(s2); // subs
  676. }
  677. m_wndPlaylistBar.Open(fns, false);
  678. OpenCurPlaylistItem(max(rtStart, 0));
  679. }
  680. }
  681. void CMainFrame::OnUpdateFavoritesFile(CCmdUI* pCmdUI)
  682. {
  683. UINT nID = pCmdUI->m_nID - ID_FAVORITES_FILE_START;
  684. }
  685. void CMainFrame::OnFavoritesDVD(UINT nID)
  686. {
  687. nID -= ID_FAVORITES_DVD_START;
  688. CList<CString> sl;
  689. AfxGetAppSettings().GetFav(FAV_DVD, sl);
  690. if(POSITION pos = sl.FindIndex(nID))
  691. {
  692. CString fn;
  693. CDVDStateStream stream;
  694. stream.AddRef();
  695. int i = 0, j = 0;
  696. for(CString s1 = sl.GetAt(pos), s2 = s1.Tokenize(_T(";"), i); 
  697. !s2.IsEmpty(); 
  698. s2 = s1.Tokenize(_T(";"), i), j++)
  699. {
  700. if(j == 0) ; // desc
  701. else if(j == 1 && s2 != _T("0")) // state
  702. {
  703. StringToBin(s2, stream.m_data);
  704. }
  705. else if(j == 2) fn = s2; // path
  706. }
  707. SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
  708. CComPtr<IDvdState> pDvdState;
  709. HRESULT hr = OleLoadFromStream((IStream*)&stream, IID_IDvdState, (void**)&pDvdState);
  710. CAutoPtr<OpenDVDData> p(new OpenDVDData());
  711. if(p) {p->path = fn; p->pDvdState = pDvdState;}
  712. OpenMedia(p);
  713. }
  714. }
  715. void CMainFrame::OnUpdateFavoritesDVD(CCmdUI* pCmdUI)
  716. {
  717. UINT nID = pCmdUI->m_nID - ID_FAVORITES_DVD_START;
  718. }
  719. void CMainFrame::OnFavoritesDevice(UINT nID)
  720. {
  721. nID -= ID_FAVORITES_DEVICE_START;
  722. }
  723. void CMainFrame::OnUpdateFavoritesDevice(CCmdUI* pCmdUI)
  724. {
  725. UINT nID = pCmdUI->m_nID - ID_FAVORITES_DEVICE_START;
  726. }
  727. // help
  728. void CMainFrame::OnHelpHomepage()
  729. {
  730. ShellExecute(m_hWnd, _T("open"), _T("http://gabest.org/"), NULL, NULL, SW_SHOWDEFAULT);
  731. }
  732. void CMainFrame::OnHelpDocumentation()
  733. {
  734. ShellExecute(m_hWnd, _T("open"), _T("http://sourceforge.net/project/showfiles.php?group_id=82303&package_id=144472"), NULL, NULL, SW_SHOWDEFAULT);
  735. }
  736. void CMainFrame::OnHelpDonate()
  737. {
  738. const TCHAR URL[] = _T("http://order.kagi.com/?N4A");
  739. if(CString(URL).Find(CString(_T("A4N")).MakeReverse()) >= 0)
  740. ShellExecute(m_hWnd, _T("open"), URL, NULL, NULL, SW_SHOWDEFAULT);
  741. }
  742. //////////////////////////////////
  743. void CMainFrame::SetDefaultWindowRect()
  744. {
  745. AppSettings& s = AfxGetAppSettings();
  746. {
  747. CRect r1, r2;
  748. GetClientRect(&r1);
  749. m_wndView.GetClientRect(&r2);
  750. CSize logosize = m_wndView.GetLogoSize();
  751. int _DEFCLIENTW = max(logosize.cx, DEFCLIENTW);
  752. int _DEFCLIENTH = max(logosize.cy, DEFCLIENTH);
  753. DWORD style = GetStyle();
  754. MENUBARINFO mbi;
  755. memset(&mbi, 0, sizeof(mbi));
  756. mbi.cbSize = sizeof(mbi);
  757. ::GetMenuBarInfo(m_hWnd, OBJID_MENU, 0, &mbi);
  758. int w = _DEFCLIENTW + GetSystemMetrics((style&WS_CAPTION)?SM_CXSIZEFRAME:SM_CXFIXEDFRAME)*2
  759. + r1.Width() - r2.Width();
  760. int h = _DEFCLIENTH + GetSystemMetrics((style&WS_CAPTION)?SM_CYSIZEFRAME:SM_CYFIXEDFRAME)*2
  761. + (mbi.rcBar.bottom - mbi.rcBar.top)
  762. + r1.Height() - r2.Height()
  763. + 1; // ???
  764. // + 2; // ???
  765. if(style&WS_CAPTION) h += GetSystemMetrics(SM_CYCAPTION);
  766. if(s.HasFixedWindowSize())
  767. {
  768. w = s.fixedWindowSize.cx;
  769. h = s.fixedWindowSize.cy;
  770. }
  771. else if(s.fRememberWindowSize)
  772. {
  773. w = s.rcLastWindowPos.Width();
  774. h = s.rcLastWindowPos.Height();
  775. }
  776. MONITORINFO mi;
  777. mi.cbSize = sizeof(MONITORINFO);
  778. GetMonitorInfo(MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST), &mi);
  779. int x = (mi.rcWork.left+mi.rcWork.right-w)/2;
  780. int y = (mi.rcWork.top+mi.rcWork.bottom-h)/2;
  781. if(s.fRememberWindowPos)
  782. {
  783. CRect r = s.rcLastWindowPos;
  784. // x = r.CenterPoint().x - w/2;
  785. // y = r.CenterPoint().y - h/2;
  786. x = r.TopLeft().x;
  787. y = r.TopLeft().y;
  788. }
  789. UINT lastWindowType = s.lastWindowType;
  790. MoveWindow(x, y, w, h);
  791. if(s.fRememberWindowSize && s.fRememberWindowPos)
  792. {
  793. WINDOWPLACEMENT wp;
  794. memset(&wp, 0, sizeof(wp));
  795. wp.length = sizeof(WINDOWPLACEMENT);
  796. if(lastWindowType == SIZE_MAXIMIZED)
  797. ShowWindow(SW_MAXIMIZE);
  798. else if(lastWindowType == SIZE_MINIMIZED)
  799. ShowWindow(SW_MINIMIZE);
  800. }
  801. }
  802. if(s.fHideCaptionMenu)
  803. {
  804. ModifyStyle(WS_CAPTION, 0, SWP_NOZORDER);
  805. ::SetMenu(m_hWnd, NULL);
  806. SetWindowPos(NULL, 0, 0, 0, 0, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER);
  807. }
  808. }
  809. void CMainFrame::RestoreDefaultWindowRect()
  810. {
  811. AppSettings& s = AfxGetAppSettings();
  812. WINDOWPLACEMENT wp;
  813. GetWindowPlacement(&wp);
  814. if(!m_fFullScreen && wp.showCmd != SW_SHOWMAXIMIZED && wp.showCmd != SW_SHOWMINIMIZED
  815. // && (GetExStyle()&WS_EX_APPWINDOW)
  816. && !s.fRememberWindowSize)
  817. {
  818. CRect r1, r2;
  819. GetClientRect(&r1);
  820. m_wndView.GetClientRect(&r2);
  821. CSize logosize = m_wndView.GetLogoSize();
  822. int _DEFCLIENTW = max(logosize.cx, DEFCLIENTW);
  823. int _DEFCLIENTH = max(logosize.cy, DEFCLIENTH);
  824. DWORD style = GetStyle();
  825. MENUBARINFO mbi;
  826. memset(&mbi, 0, sizeof(mbi));
  827. mbi.cbSize = sizeof(mbi);
  828. ::GetMenuBarInfo(m_hWnd, OBJID_MENU, 0, &mbi);
  829. int w = _DEFCLIENTW + GetSystemMetrics((style&WS_CAPTION)?SM_CXSIZEFRAME:SM_CXFIXEDFRAME)*2
  830. + r1.Width() - r2.Width();
  831. int h = _DEFCLIENTH + GetSystemMetrics((style&WS_CAPTION)?SM_CYSIZEFRAME:SM_CYFIXEDFRAME)*2
  832. + (mbi.rcBar.bottom - mbi.rcBar.top)
  833. + r1.Height() - r2.Height()
  834. + 1; // ???
  835. // + 2; // ???
  836. if(style&WS_CAPTION) h += GetSystemMetrics(SM_CYCAPTION);
  837. if(s.HasFixedWindowSize())
  838. {
  839. w = s.fixedWindowSize.cx;
  840. h = s.fixedWindowSize.cy;
  841. }
  842. CRect r;
  843. GetWindowRect(r);
  844. int x = r.CenterPoint().x - w/2;
  845. int y = r.CenterPoint().y - h/2;
  846. if(s.fRememberWindowPos)
  847. {
  848. CRect r = s.rcLastWindowPos;
  849. x = r.TopLeft().x;
  850. y = r.TopLeft().y;
  851. }
  852. MoveWindow(x, y, w, h);
  853. }
  854. }
  855. OAFilterState CMainFrame::GetMediaState()
  856. {
  857. OAFilterState ret = -1;
  858. if(m_iMediaLoadState == MLS_LOADED) pMC->GetState(0, &ret);
  859. return(ret);
  860. }
  861. CSize CMainFrame::GetVideoSize()
  862. {
  863. bool fKeepAspectRatio = AfxGetAppSettings().fKeepAspectRatio;
  864. bool fCompMonDeskARDiff = AfxGetAppSettings().fCompMonDeskARDiff;
  865. CSize ret(0,0);
  866. if(m_iMediaLoadState != MLS_LOADED || m_fAudioOnly)
  867. return ret;
  868. CSize wh(0, 0), arxy(0, 0);
  869. if(m_pCAP)
  870. {
  871. wh = m_pCAP->GetVideoSize(false);
  872. arxy = m_pCAP->GetVideoSize(fKeepAspectRatio);
  873. }
  874. else
  875. {
  876. pBV->GetVideoSize(&wh.cx, &wh.cy);
  877. long arx = 0, ary = 0;
  878. CComQIPtr<IBasicVideo2> pBV2 = pBV;
  879. if(pBV2 && SUCCEEDED(pBV2->GetPreferredAspectRatio(&arx, &ary)) && arx > 0 && ary > 0)
  880. arxy.SetSize(arx, ary);
  881. }
  882. CSize& ar = AfxGetAppSettings().AspectRatio;
  883. if(ar.cx && ar.cy) arxy = ar;
  884. if(wh.cx <= 0 || wh.cy <= 0)
  885. return ret;
  886. // with the overlay mixer IBasicVideo2 won't tell the new AR when changed dynamically
  887. DVD_VideoAttributes VATR;
  888. if(m_iPlaybackMode == PM_DVD && SUCCEEDED(pDVDI->GetCurrentVideoAttributes(&VATR)))
  889. arxy.SetSize(VATR.ulAspectX, VATR.ulAspectY);
  890. ret = (!fKeepAspectRatio || arxy.cx <= 0 || arxy.cy <= 0)
  891. ? wh
  892. : CSize(MulDiv(wh.cy, arxy.cx, arxy.cy), wh.cy);
  893. if(fCompMonDeskARDiff)
  894. if(HDC hDC = ::GetDC(0))
  895. {
  896. int _HORZSIZE = GetDeviceCaps(hDC, HORZSIZE);
  897. int _VERTSIZE = GetDeviceCaps(hDC, VERTSIZE);
  898. int _HORZRES = GetDeviceCaps(hDC, HORZRES);
  899. int _VERTRES = GetDeviceCaps(hDC, VERTRES);
  900. if(_HORZSIZE > 0 && _VERTSIZE > 0 && _HORZRES > 0 && _VERTRES > 0)
  901. {
  902. double a = 1.0*_HORZSIZE/_VERTSIZE;
  903. double b = 1.0*_HORZRES/_VERTRES;
  904. if(b < a)
  905. ret.cy = (DWORD)(1.0*ret.cy * a / b);
  906. else if(a < b)
  907. ret.cx = (DWORD)(1.0*ret.cx * b / a);
  908. }
  909. ::ReleaseDC(0, hDC);
  910. }
  911. return ret;
  912. }
  913. void CMainFrame::ToggleFullscreen(bool fToNearest, bool fSwitchScreenResWhenHasTo)
  914. {
  915. CRect r;
  916. // const CWnd* pWndInsertAfter;
  917. DWORD dwRemove = 0, dwAdd = 0;
  918. DWORD dwRemoveEx = 0, dwAddEx = 0;
  919. HMENU hMenu;
  920. if(!m_fFullScreen)
  921. {
  922. GetWindowRect(&m_lastWindowRect);
  923. dispmode& dm = AfxGetAppSettings().dmFullscreenRes;
  924. m_dmBeforeFullscreen.fValid = false;
  925. if(dm.fValid && fSwitchScreenResWhenHasTo)
  926. {
  927. GetCurDispMode(m_dmBeforeFullscreen);
  928. SetDispMode(dm);
  929. }
  930. MONITORINFO mi;
  931. mi.cbSize = sizeof(MONITORINFO);
  932. GetMonitorInfo(MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST), &mi);
  933. dwRemove = WS_CAPTION|WS_THICKFRAME;
  934. if(fToNearest) r = mi.rcMonitor;
  935. else GetDesktopWindow()->GetWindowRect(&r);
  936. hMenu = NULL;
  937. }
  938. else
  939. {
  940. if(m_dmBeforeFullscreen.fValid)
  941. SetDispMode(m_dmBeforeFullscreen);
  942. dwAdd = (AfxGetAppSettings().fHideCaptionMenu ? 0 : WS_CAPTION) | WS_THICKFRAME;
  943. r = m_lastWindowRect;
  944. hMenu = AfxGetAppSettings().fHideCaptionMenu ? NULL : m_hMenuDefault;
  945. }
  946. m_lastMouseMove.x = m_lastMouseMove.y = -1;
  947. bool fAudioOnly = m_fAudioOnly;
  948. m_fAudioOnly = true;
  949. m_fFullScreen = !m_fFullScreen;
  950. SetAlwaysOnTop(AfxGetAppSettings().iOnTop);
  951. ModifyStyle(dwRemove, dwAdd, SWP_NOZORDER);
  952. ModifyStyleEx(dwRemoveEx, dwAddEx, SWP_NOZORDER);
  953. ::SetMenu(m_hWnd, hMenu);
  954. SetWindowPos(NULL, r.left, r.top, r.Width(), r.Height(), SWP_NOZORDER|SWP_NOSENDCHANGING /*SWP_FRAMECHANGED*/);
  955. if(m_fFullScreen)
  956. {
  957. m_fHideCursor = true;
  958.         ShowControls(CS_NONE, false);
  959. }
  960. else
  961. {
  962. KillTimer(TIMER_FULLSCREENCONTROLBARHIDER);
  963. KillTimer(TIMER_FULLSCREENMOUSEHIDER);
  964. m_fHideCursor = false;
  965.         ShowControls(AfxGetAppSettings().nCS);
  966. }
  967. m_wndView.SetWindowPos(NULL, 0, 0, 0, 0, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER);
  968. m_fAudioOnly = fAudioOnly;
  969. MoveVideoWindow();
  970. }
  971. void CMainFrame::MoveVideoWindow(bool fShowStats)
  972. {
  973. if(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly && IsWindowVisible())
  974. {
  975. CRect wr;
  976. if(!m_fFullScreen)
  977. {
  978. m_wndView.GetClientRect(wr);
  979. if(!AfxGetAppSettings().fHideCaptionMenu)
  980. wr.DeflateRect(2, 2);
  981. }
  982. else
  983. {
  984. GetWindowRect(&wr);
  985. // HACK
  986. CRect r;
  987. m_wndView.GetWindowRect(&r);
  988. wr -= r.TopLeft();
  989. }
  990. CRect vr = CRect(0,0,0,0);
  991. OAFilterState fs = GetMediaState();
  992. if(fs == State_Paused || fs == State_Running || fs == State_Stopped && (m_fShockwaveGraph || m_fQuicktimeGraph))
  993. {
  994. CSize arxy = GetVideoSize();
  995. int iDefaultVideoSize = AfxGetAppSettings().iDefaultVideoSize;
  996. CSize ws = 
  997. iDefaultVideoSize == DVS_HALF ? CSize(arxy.cx/2, arxy.cy/2) :
  998. iDefaultVideoSize == DVS_NORMAL ? arxy :
  999. iDefaultVideoSize == DVS_DOUBLE ? CSize(arxy.cx*2, arxy.cy*2) :
  1000. wr.Size();
  1001. int w = ws.cx;
  1002. int h = ws.cy;
  1003. if(!m_fShockwaveGraph) //&& !m_fQuicktimeGraph)
  1004. {
  1005. if(iDefaultVideoSize == DVS_FROMINSIDE || iDefaultVideoSize == DVS_FROMOUTSIDE)
  1006. {
  1007. h = ws.cy;
  1008. w = MulDiv(h, arxy.cx, arxy.cy);
  1009. if(iDefaultVideoSize == DVS_FROMINSIDE && w > ws.cx
  1010. || iDefaultVideoSize == DVS_FROMOUTSIDE && w < ws.cx)
  1011. {
  1012. w = ws.cx;
  1013. h = MulDiv(w, arxy.cy, arxy.cx);
  1014. }
  1015. }
  1016. }
  1017. CSize size(
  1018. (int)(m_ZoomX*w), 
  1019. (int)(m_ZoomY*h));
  1020. CPoint pos(
  1021. (int)(m_PosX*(wr.Width()*3 - m_ZoomX*w) - wr.Width()), 
  1022. (int)(m_PosY*(wr.Height()*3 - m_ZoomY*h) - wr.Height()));
  1023. /* CPoint pos(
  1024. (int)(m_PosX*(wr.Width() - size.cx)), 
  1025. (int)(m_PosY*(wr.Height() - size.cy)));
  1026. */
  1027. vr = CRect(pos, size);
  1028. }
  1029. wr |= CRect(0,0,0,0);
  1030. vr |= CRect(0,0,0,0);
  1031. if(m_pCAP)
  1032. {
  1033. m_pCAP->SetPosition(wr, vr);
  1034. }
  1035. else
  1036. {
  1037. HRESULT hr;
  1038. hr = pBV->SetDefaultSourcePosition();
  1039. hr = pBV->SetDestinationPosition(vr.left, vr.top, vr.Width(), vr.Height());
  1040. hr = pVW->SetWindowPosition(wr.left, wr.top, wr.Width(), wr.Height());
  1041. }
  1042. m_wndView.SetVideoRect(wr);
  1043. if(fShowStats && vr.Height() > 0)
  1044. {
  1045. CString info;
  1046. info.Format(_T("Pos %.2f %.2f, Zoom %.2f %.2f, AR %.2f"), m_PosX, m_PosY, m_ZoomX, m_ZoomY, (float)vr.Width()/vr.Height());
  1047. SendStatusMessage(info, 3000);
  1048. }
  1049. }
  1050. else
  1051. {
  1052. m_wndView.SetVideoRect();
  1053. }
  1054. }
  1055. void CMainFrame::ZoomVideoWindow(double scale)
  1056. {
  1057. if(m_iMediaLoadState != MLS_LOADED)
  1058. return;
  1059. AppSettings& s = AfxGetAppSettings();
  1060. if(scale <= 0)
  1061. {
  1062. scale = s.iZoomLevel == 0 ? 0.5 : s.iZoomLevel == 2 ? 2.0 : 1.0;
  1063. }
  1064. if(m_fFullScreen)
  1065. {
  1066. OnViewFullscreen();
  1067. }
  1068. MINMAXINFO mmi;
  1069. OnGetMinMaxInfo(&mmi);
  1070. CRect r;
  1071. int w = 0, h = 0;
  1072. if(!m_fAudioOnly)
  1073. {
  1074. CSize arxy = GetVideoSize();
  1075. long lWidth = int(arxy.cx * scale + 0.5);
  1076. long lHeight = int(arxy.cy * scale + 0.5);
  1077. DWORD style = GetStyle();
  1078. CRect r1, r2;
  1079. GetClientRect(&r1);
  1080. m_wndView.GetClientRect(&r2);
  1081. w = GetSystemMetrics((style&WS_CAPTION)?SM_CXSIZEFRAME:SM_CXFIXEDFRAME)*2
  1082. + r1.Width() - r2.Width()
  1083. + lWidth;
  1084. MENUBARINFO mbi;
  1085. memset(&mbi, 0, sizeof(mbi));
  1086. mbi.cbSize = sizeof(mbi);
  1087. ::GetMenuBarInfo(m_hWnd, OBJID_MENU, 0, &mbi);
  1088. h = GetSystemMetrics((style&WS_CAPTION)?SM_CYSIZEFRAME:SM_CYFIXEDFRAME)*2
  1089. + (mbi.rcBar.bottom - mbi.rcBar.top)
  1090. + r1.Height() - r2.Height()
  1091. + lHeight;
  1092. if(style&WS_CAPTION)
  1093. {
  1094. h += GetSystemMetrics(SM_CYCAPTION);
  1095. w += 2; h += 2; // for the 1 pixel wide sunken frame
  1096. w += 2; h += 3; // for the inner black border
  1097. }
  1098. GetWindowRect(r);
  1099. w = max(w, mmi.ptMinTrackSize.x);
  1100. h = max(h, mmi.ptMinTrackSize.y);
  1101. }
  1102. else
  1103. {
  1104. GetWindowRect(r);
  1105. w = r.Width(); // mmi.ptMinTrackSize.x;
  1106. h = mmi.ptMinTrackSize.y;
  1107. }
  1108. // center window
  1109. if(!s.fRememberWindowPos)
  1110. {
  1111. CPoint cp = r.CenterPoint();
  1112. r.left = cp.x - w/2;
  1113. r.top = cp.y - h/2;
  1114. }
  1115. r.right = r.left + w;
  1116. r.bottom = r.top + h;
  1117. MONITORINFO mi;
  1118. mi.cbSize = sizeof(MONITORINFO);
  1119. GetMonitorInfo(MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST), &mi);
  1120. if(r.right > mi.rcWork.right) r.OffsetRect(mi.rcWork.right-r.right, 0);
  1121. if(r.left < mi.rcWork.left) r.OffsetRect(mi.rcWork.left-r.left, 0);
  1122. if(r.bottom > mi.rcWork.bottom) r.OffsetRect(0, mi.rcWork.bottom-r.bottom);
  1123. if(r.top < mi.rcWork.top) r.OffsetRect(0, mi.rcWork.top-r.top);
  1124. if(m_fFullScreen || !s.HasFixedWindowSize())
  1125. {
  1126. MoveWindow(r);
  1127. }
  1128. // ShowWindow(SW_SHOWNORMAL);
  1129. MoveVideoWindow();
  1130. }
  1131. void CMainFrame::RepaintVideo()
  1132. {
  1133. if(m_pCAP) m_pCAP->Paint(false);
  1134. }
  1135. void CMainFrame::SetBalance(int balance)
  1136. {
  1137. AfxGetAppSettings().nBalance = balance;
  1138. int sign = balance>0?-1:1;
  1139. balance = max(100-abs(balance), 1);
  1140. balance = (int)((log10(1.0*balance)-2)*5000*sign);
  1141. balance = max(min(balance, 10000), -10000);
  1142. if(m_iMediaLoadState == MLS_LOADED) 
  1143. pBA->put_Balance(balance);
  1144. }
  1145. void CMainFrame::SetupIViAudReg()
  1146. {
  1147. if(!AfxGetAppSettings().fAutoSpeakerConf) return;
  1148. DWORD spc = 0, defchnum = 0;
  1149. if(AfxGetAppSettings().fAutoSpeakerConf)
  1150. {
  1151. CComPtr<IDirectSound> pDS;
  1152. if(SUCCEEDED(DirectSoundCreate(NULL, &pDS, NULL))
  1153. && SUCCEEDED(pDS->SetCooperativeLevel(m_hWnd, DSSCL_NORMAL)))
  1154. {
  1155. if(SUCCEEDED(pDS->GetSpeakerConfig(&spc)))
  1156. {
  1157. switch(spc)
  1158. {
  1159. case DSSPEAKER_DIRECTOUT: defchnum = 6; break;
  1160. case DSSPEAKER_HEADPHONE: defchnum = 2; break;
  1161. case DSSPEAKER_MONO: defchnum = 1; break;
  1162. case DSSPEAKER_QUAD: defchnum = 4; break;
  1163. default:
  1164. case DSSPEAKER_STEREO: defchnum = 2; break;
  1165. case DSSPEAKER_SURROUND: defchnum = 2; break;
  1166. case DSSPEAKER_5POINT1: defchnum = 5; break;
  1167. case DSSPEAKER_7POINT1: defchnum = 5; break;
  1168. }
  1169. }
  1170. }
  1171. }
  1172. else
  1173. {
  1174. defchnum = 2;
  1175. }
  1176. CRegKey iviaud;
  1177. if(ERROR_SUCCESS == iviaud.Create(HKEY_LOCAL_MACHINE, _T("SOFTWARE\InterVideo\Common\AudioDec")))
  1178. {
  1179. DWORD chnum = 0;
  1180. if(FAILED(iviaud.QueryDWORDValue(_T("AUDIO"), chnum))) chnum = 0;
  1181. if(chnum <= defchnum) // check if the user has already set it..., but we won't skip if it's lower than sensible :P
  1182. iviaud.SetDWORDValue(_T("AUDIO"), defchnum);
  1183. }
  1184. }
  1185. //
  1186. // Open/Close
  1187. //
  1188. void CMainFrame::OpenCreateGraphObject(OpenMediaData* pOMD)
  1189. {
  1190. pGB = NULL;
  1191. m_fCustomGraph = false;
  1192. m_fRealMediaGraph = m_fShockwaveGraph = m_fQuicktimeGraph = false;
  1193. if(OpenFileData* p = dynamic_cast<OpenFileData*>(pOMD))
  1194. {
  1195. AppSettings& s = AfxGetAppSettings();
  1196. engine_t engine = s.Formats.GetEngine(p->fns.GetHead());
  1197. CStringA ct = GetContentType(p->fns.GetHead());
  1198. if(ct == "video/x-ms-asf")
  1199. {
  1200. // TODO: put something here to make the windows media source filter load later
  1201. }
  1202. else if(ct == "audio/x-pn-realaudio"
  1203. || ct == "audio/x-pn-realaudio-plugin"
  1204. || ct == "audio/x-realaudio-secure"
  1205. || ct == "video/vnd.rn-realvideo-secure"
  1206. || ct == "application/vnd.rn-realmedia"
  1207. || ct.Find("vnd.rn-") >= 0
  1208. || ct.Find("realaudio") >= 0
  1209. || ct.Find("realvideo") >= 0)
  1210. {
  1211. engine = RealMedia;
  1212. }
  1213. else if(ct == "application/x-shockwave-flash")
  1214. {
  1215. engine = ShockWave;
  1216. }
  1217. else if(ct == "video/quicktime"
  1218. || ct == "application/x-quicktimeplayer")
  1219. {
  1220. engine = QuickTime;
  1221. }
  1222. HRESULT hr;
  1223. CComPtr<IUnknown> pUnk;
  1224. if(engine == RealMedia)
  1225. {
  1226. if(!(pUnk = (IUnknown*)(INonDelegatingUnknown*)new CRealMediaGraph(m_wndView.m_hWnd, hr)))
  1227. throw _T("Out of memory");
  1228. m_pCAP = CComQIPtr<ISubPicAllocatorPresenter>(pUnk);
  1229. // if(FAILED(hr) || !(pGB = CComQIPtr<IGraphBuilder>(pUnk)))
  1230. // throw _T("RealMedia files require RealPlayer/RealOne to be installed");
  1231. if(SUCCEEDED(hr) && !!(pGB = CComQIPtr<IGraphBuilder>(pUnk)))
  1232. m_fRealMediaGraph = true;
  1233. }
  1234. else if(engine == ShockWave)
  1235. {
  1236. if(!(pUnk = (IUnknown*)(INonDelegatingUnknown*)new CShockwaveGraph(m_wndView.m_hWnd, hr)))
  1237. throw _T("Out of memory");
  1238. if(FAILED(hr) || !(pGB = CComQIPtr<IGraphBuilder>(pUnk)))
  1239. throw _T("Can't create shockwave control");
  1240. m_fShockwaveGraph = true;
  1241. }
  1242. else if(engine == QuickTime)
  1243. {
  1244. if(!(pUnk = (IUnknown*)(INonDelegatingUnknown*)new CQuicktimeGraph(m_wndView.m_hWnd, hr)))
  1245. throw _T("Out of memory");
  1246. m_pCAP = CComQIPtr<ISubPicAllocatorPresenter>(pUnk);
  1247. // if(FAILED(hr) || !(pGB = CComQIPtr<IGraphBuilder>(pUnk)))
  1248. // throw _T("Can't initialize QuickTime");
  1249. if(SUCCEEDED(hr) && !!(pGB = CComQIPtr<IGraphBuilder>(pUnk)))
  1250.                 m_fQuicktimeGraph = true;
  1251. }
  1252. m_fCustomGraph = m_fRealMediaGraph || m_fShockwaveGraph || m_fQuicktimeGraph;
  1253. }
  1254. if(!m_fCustomGraph)
  1255. {
  1256. if(FAILED(pGB.CoCreateInstance(CLSID_FilterGraph)))
  1257. {
  1258. throw _T("Failed to create the filter graph object");
  1259. }
  1260. }
  1261. pMC = pGB; pME = pGB; pMS = pGB; // general
  1262. pVW = pGB; pBV = pGB; // video
  1263. pBA = pGB; // audio
  1264. pFS = pGB;
  1265. if(!(pMC && pME && pMS)
  1266. || !(pVW && pBV)
  1267. || !(pBA))
  1268. {
  1269. throw _T("Failed to query the needed interfaces for playback");
  1270. }
  1271. if(FAILED(pME->SetNotifyWindow((OAHWND)m_hWnd, WM_GRAPHNOTIFY, 0)))
  1272. {
  1273. throw _T("Could not set target window for graph notification");
  1274. }
  1275. m_pProv = (IUnknown*)new CKeyProvider();
  1276. if(CComQIPtr<IObjectWithSite> pObjectWithSite = pGB)
  1277. pObjectWithSite->SetSite(m_pProv);
  1278. m_pCB = new CDSMChapterBag(NULL, NULL);
  1279. }
  1280. void CMainFrame::OpenFile(OpenFileData* pOFD)
  1281. {
  1282. if(pOFD->fns.IsEmpty())
  1283. throw _T("Invalid argument");
  1284. AppSettings& s = AfxGetAppSettings();
  1285.     CGraphBuilderFile gb(pGB, m_wndView.m_hWnd);
  1286. bool fFirst = true;
  1287. POSITION pos = pOFD->fns.GetHeadPosition();
  1288. while(pos)
  1289. {
  1290. CString fn = pOFD->fns.GetNext(pos);
  1291. fn.Trim();
  1292. if(fn.IsEmpty() && !fFirst)
  1293. break;
  1294. HRESULT hr = gb.Render(fn);
  1295. if(FAILED(hr))
  1296. {
  1297. if(fFirst)
  1298. {
  1299. if(s.fReportFailedPins && gb.GetDeadEnd(0))
  1300. {
  1301. CMediaTypesDlg(gb, this).DoModal();
  1302. if(gb.GetStreamCount() == 0)
  1303. throw _T("Cannot render any of the streams");
  1304. }
  1305. CString err;
  1306. switch(hr)
  1307. {
  1308. case E_ABORT: err = _T("Opening aborted"); break;
  1309. case E_FAIL: case E_POINTER: default: err = _T("Failed to render the file"); break;
  1310. case E_INVALIDARG: err = _T("Invalid file name"); break;
  1311. case E_OUTOFMEMORY: err = _T("Out of memory"); break;
  1312. case VFW_E_CANNOT_CONNECT: err = _T("Cannot connect the filters"); break;
  1313. case VFW_E_CANNOT_LOAD_SOURCE_FILTER: err = _T("Cannot load any source filter"); break;
  1314. case VFW_E_CANNOT_RENDER: err = _T("Cannot render the file"); break;
  1315. case VFW_E_INVALID_FILE_FORMAT: err = _T("Invalid file format"); break;
  1316. case VFW_E_NOT_FOUND: err = _T("File not found"); break;
  1317. case VFW_E_UNKNOWN_FILE_TYPE: err = _T("Unknown file type"); break;
  1318. case VFW_E_UNSUPPORTED_STREAM: err = _T("Unsupported stream"); break;
  1319. }
  1320. throw err;
  1321. }
  1322. }
  1323. if(s.fKeepHistory)
  1324. {
  1325. CRecentFileList* pMRU = fFirst ? &s.MRU : &s.MRUDub;
  1326. pMRU->ReadList();
  1327. pMRU->Add(fn);
  1328. pMRU->WriteList();
  1329. }
  1330. if(fFirst)
  1331. {
  1332. pOFD->title = fn;
  1333. }
  1334. fFirst = false;
  1335. if(m_fCustomGraph) break;
  1336. }
  1337. if(s.fReportFailedPins && gb.GetDeadEnd(0))
  1338. CMediaTypesDlg(gb, this).DoModal();
  1339. if(!m_fCustomGraph)
  1340. gb.FindInterface(__uuidof(ISubPicAllocatorPresenter), (void**)&m_pCAP);
  1341. if(!(pAMOP = pGB))
  1342. {
  1343. BeginEnumFilters(pGB, pEF, pBF)
  1344. if(pAMOP = pBF) break;
  1345. EndEnumFilters
  1346. }
  1347. if(FindFilter(__uuidof(CShoutcastSource), pGB))
  1348. m_fUpdateInfoBar = true;
  1349. SetupChapters();
  1350. CComQIPtr<IKeyFrameInfo> pKFI;
  1351. BeginEnumFilters(pGB, pEF, pBF)
  1352. if(pKFI = pBF) break;
  1353. EndEnumFilters
  1354. UINT nKFs = 0, nKFsTmp = 0;
  1355. if(pKFI && S_OK == pKFI->GetKeyFrameCount(nKFs) && nKFs > 0)
  1356. {
  1357. m_kfs.SetSize(nKFsTmp = nKFs);
  1358. if(S_OK != pKFI->GetKeyFrames(&TIME_FORMAT_MEDIA_TIME, m_kfs.GetData(), nKFsTmp) || nKFsTmp != nKFs)
  1359. m_kfs.SetSize(0);
  1360. }
  1361. m_iPlaybackMode = PM_FILE;
  1362. }
  1363. void CMainFrame::SetupChapters()
  1364. {
  1365. ASSERT(m_pCB);
  1366. m_pCB->ChapRemoveAll();
  1367. CInterfaceList<IBaseFilter> pBFs;
  1368. BeginEnumFilters(pGB, pEF, pBF) 
  1369. pBFs.AddTail(pBF);
  1370. EndEnumFilters
  1371. POSITION pos;
  1372. pos = pBFs.GetHeadPosition();
  1373. while(pos && !m_pCB->ChapGetCount())
  1374. {
  1375. IBaseFilter* pBF = pBFs.GetNext(pos);
  1376. CComQIPtr<IDSMChapterBag> pCB = pBF;
  1377. if(!pCB) continue;
  1378. for(DWORD i = 0, cnt = pCB->ChapGetCount(); i < cnt; i++)
  1379. {
  1380. REFERENCE_TIME rt;
  1381. CComBSTR name;
  1382. if(SUCCEEDED(pCB->ChapGet(i, &rt, &name)))
  1383. m_pCB->ChapAppend(rt, name);
  1384. }
  1385. }
  1386. pos = pBFs.GetHeadPosition();
  1387. while(pos && !m_pCB->ChapGetCount())
  1388. {
  1389. IBaseFilter* pBF = pBFs.GetNext(pos);
  1390. CComQIPtr<IChapterInfo> pCI = pBF;
  1391. if(!pCI) continue;
  1392. CHAR iso6391[3];
  1393. ::GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SISO639LANGNAME, iso6391, 3);
  1394. CStringA iso6392 = ISO6391To6392(iso6391);
  1395. if(iso6392.GetLength() < 3) iso6392 = "eng";
  1396. UINT cnt = pCI->GetChapterCount(CHAPTER_ROOT_ID);
  1397. for(UINT i = 1; i <= cnt; i++)
  1398. {
  1399. UINT cid = pCI->GetChapterId(CHAPTER_ROOT_ID, i);
  1400. ChapterElement ce;
  1401. if(pCI->GetChapterInfo(cid, &ce))
  1402. {
  1403. char pl[3] = {iso6392[0], iso6392[1], iso6392[2]};
  1404. char cc[] = "  ";
  1405. CComBSTR name;
  1406. name.Attach(pCI->GetChapterStringInfo(cid, pl, cc));
  1407. m_pCB->ChapAppend(ce.rtStart, name);
  1408. }
  1409. }
  1410. }
  1411. pos = pBFs.GetHeadPosition();
  1412. while(pos && !m_pCB->ChapGetCount())
  1413. {
  1414. IBaseFilter* pBF = pBFs.GetNext(pos);
  1415. CComQIPtr<IAMExtendedSeeking, &IID_IAMExtendedSeeking> pES = pBF;
  1416. if(!pES) continue;
  1417. long MarkerCount = 0;
  1418. if(SUCCEEDED(pES->get_MarkerCount(&MarkerCount)))
  1419. {
  1420. for(long i = 1; i <= MarkerCount; i++)
  1421. {
  1422. double MarkerTime = 0;
  1423. if(SUCCEEDED(pES->GetMarkerTime(i, &MarkerTime)))
  1424. {
  1425. CStringW name;
  1426. name.Format(L"Chapter %d", i);
  1427. CComBSTR bstr;
  1428. if(S_OK == pES->GetMarkerName(i, &bstr))
  1429. name = bstr;
  1430. m_pCB->ChapAppend(REFERENCE_TIME(MarkerTime*10000000), name);
  1431. }
  1432. }
  1433. }
  1434. }
  1435. pos = pBFs.GetHeadPosition();
  1436. while(pos && !m_pCB->ChapGetCount())
  1437. {
  1438. IBaseFilter* pBF = pBFs.GetNext(pos);
  1439. if(GetCLSID(pBF) != CLSID_OggSplitter)
  1440. continue;
  1441. BeginEnumPins(pBF, pEP, pPin)
  1442. {
  1443. if(m_pCB->ChapGetCount()) break;
  1444. if(CComQIPtr<IPropertyBag> pPB = pPin)
  1445. {
  1446.              for(int i = 1; ; i++)
  1447. {
  1448. CStringW str;
  1449. CComVariant var;
  1450. var.Clear();
  1451. str.Format(L"CHAPTER%02d", i);
  1452. if(S_OK != pPB->Read(str, &var, NULL)) 
  1453. break;
  1454. int h, m, s, ms;
  1455. WCHAR wc;
  1456. if(7 != swscanf(CStringW(var), L"%d%c%d%c%d%c%d", &h, &wc, &m, &wc, &s, &wc, &ms)) 
  1457. break;
  1458. CStringW name;
  1459. name.Format(L"Chapter %d", i);
  1460. var.Clear();
  1461.                     str += L"NAME";
  1462. if(S_OK == pPB->Read(str, &var, NULL))
  1463. name = var;
  1464. m_pCB->ChapAppend(10000i64*(((h*60 + m)*60 + s)*1000 + ms), name);
  1465. }
  1466. }
  1467. }
  1468. EndEnumPins
  1469. }
  1470. m_pCB->ChapSort();
  1471. }
  1472. void CMainFrame::OpenDVD(OpenDVDData* pODD)
  1473. {
  1474. CGraphBuilderDVD gb(pGB, m_wndView.m_hWnd);
  1475. HRESULT hr = gb.Render(pODD->path, pODD->title);
  1476. AppSettings& s = AfxGetAppSettings();
  1477. if(hr == VFW_E_CANNOT_LOAD_SOURCE_FILTER)
  1478. throw _T("Can't find DVD directory");
  1479. else if(hr == VFW_E_CANNOT_RENDER)
  1480. throw _T("Failed to render all pins of the DVD Navigator filter");
  1481. else if(hr == VFW_S_PARTIAL_RENDER)
  1482. {
  1483. if(s.fReportFailedPins && gb.GetDeadEnd(0))
  1484. CMediaTypesDlg(gb, this).DoModal();
  1485. throw _T("Failed to render some of the pins of the DVD Navigator filter");
  1486. }
  1487. else if(hr == E_NOINTERFACE)
  1488. throw _T("Failed to query the needed interfaces for DVD playback");
  1489. else if(FAILED(hr))
  1490. throw _T("Can't create the DVD Navigator filter");
  1491. gb.FindInterface(__uuidof(ISubPicAllocatorPresenter), (void**)&m_pCAP);
  1492. gb.FindInterface(__uuidof(IDvdControl2), (void**)&pDVDC);
  1493. gb.FindInterface(__uuidof(IDvdInfo2), (void**)&pDVDI);
  1494. if(!pDVDC || !pDVDI)
  1495. throw _T("Failed to query the needed interfaces for DVD playback");
  1496. if(s.idMenuLang)
  1497. pDVDC->SelectDefaultMenuLanguage(s.idMenuLang);
  1498. if(s.idAudioLang)
  1499. pDVDC->SelectDefaultAudioLanguage(s.idAudioLang, DVD_AUD_EXT_NotSpecified);
  1500. if(s.idSubtitlesLang)
  1501. pDVDC->SelectDefaultSubpictureLanguage(s.idSubtitlesLang, DVD_SP_EXT_NotSpecified);
  1502. m_iDVDDomain = DVD_DOMAIN_Stop;
  1503. m_iPlaybackMode = PM_DVD;
  1504. }
  1505. void CMainFrame::OpenCapture(OpenDeviceData* pODD)
  1506. {
  1507. CStringW vidfrname, audfrname;
  1508. CComPtr<IBaseFilter> pVidCapTmp, pAudCapTmp;
  1509. m_VidDispName = pODD->DisplayName[0];
  1510. if(!m_VidDispName.IsEmpty())
  1511. {
  1512. if(!CreateFilter(m_VidDispName, &pVidCapTmp, vidfrname))
  1513. throw _T("Can't create video capture filter");
  1514. }
  1515. m_AudDispName = pODD->DisplayName[1];
  1516. if(!m_AudDispName.IsEmpty())
  1517. {
  1518. if(!CreateFilter(m_AudDispName, &pAudCapTmp, audfrname))
  1519. throw _T("Can't create video capture filter");
  1520. }
  1521. if(!pVidCapTmp && !pAudCapTmp)
  1522. {
  1523. throw _T("No capture filters");
  1524. }
  1525. pCGB = NULL;
  1526. pVidCap = NULL;
  1527. pAudCap = NULL;
  1528. if(FAILED(pCGB.CoCreateInstance(CLSID_CaptureGraphBuilder2)))
  1529. {
  1530. throw _T("Can't create capture graph builder object");
  1531. }
  1532. HRESULT hr;
  1533. pCGB->SetFiltergraph(pGB);
  1534. if(pVidCapTmp)
  1535. {
  1536. if(FAILED(hr = pGB->AddFilter(pVidCapTmp, vidfrname)))
  1537. {
  1538. throw _T("Can't add video capture filter to the graph");
  1539. }
  1540. pVidCap = pVidCapTmp;
  1541. if(!pAudCapTmp)
  1542. {
  1543. if(FAILED(pCGB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Interleaved, pVidCap, IID_IAMStreamConfig, (void **)&pAMVSCCap))
  1544. && FAILED(pCGB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pVidCap, IID_IAMStreamConfig, (void **)&pAMVSCCap)))
  1545. TRACE(_T("Warning: No IAMStreamConfig interface for vidcap capture"));
  1546. if(FAILED(pCGB->FindInterface(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Interleaved, pVidCap, IID_IAMStreamConfig, (void **)&pAMVSCPrev))
  1547. && FAILED(pCGB->FindInterface(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, pVidCap, IID_IAMStreamConfig, (void **)&pAMVSCPrev)))
  1548. TRACE(_T("Warning: No IAMStreamConfig interface for vidcap capture"));
  1549. if(FAILED(pCGB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, pVidCap, IID_IAMStreamConfig, (void **)&pAMASC))
  1550. && FAILED(pCGB->FindInterface(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Audio, pVidCap, IID_IAMStreamConfig, (void **)&pAMASC)))
  1551. {
  1552. TRACE(_T("Warning: No IAMStreamConfig interface for vidcap"));
  1553. }
  1554. else
  1555. {
  1556. pAudCap = pVidCap;
  1557. }
  1558. }
  1559. else
  1560. {
  1561. if(FAILED(pCGB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pVidCap, IID_IAMStreamConfig, (void **)&pAMVSCCap)))
  1562. TRACE(_T("Warning: No IAMStreamConfig interface for vidcap capture"));
  1563. if(FAILED(pCGB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pVidCap, IID_IAMStreamConfig, (void **)&pAMVSCPrev)))
  1564. TRACE(_T("Warning: No IAMStreamConfig interface for vidcap capture"));
  1565. }
  1566. if(FAILED(pCGB->FindInterface(&LOOK_UPSTREAM_ONLY, NULL, pVidCap, IID_IAMCrossbar, (void**)&pAMXBar)))
  1567. TRACE(_T("Warning: No IAMCrossbar interface was foundn"));
  1568. if(FAILED(pCGB->FindInterface(&LOOK_UPSTREAM_ONLY, NULL, pVidCap, IID_IAMTVTuner, (void**)&pAMTuner)))
  1569. TRACE(_T("Warning: No IAMTVTuner interface was foundn"));
  1570. /*
  1571. if(pAMVSCCap) 
  1572. {
  1573. //DumpStreamConfig(_T("c:\mpclog.txt"), pAMVSCCap);
  1574.             CComQIPtr<IAMVfwCaptureDialogs> pVfwCD = pVidCap;
  1575. if(!pAMXBar && pVfwCD)
  1576. {
  1577. m_wndCaptureBar.m_capdlg.SetupVideoControls(viddispname, pAMVSCCap, pVfwCD);
  1578. }
  1579. else
  1580. {
  1581. m_wndCaptureBar.m_capdlg.SetupVideoControls(viddispname, pAMVSCCap, pAMXBar, pAMTuner);
  1582. }
  1583. }
  1584. */
  1585. // TODO: init pAMXBar
  1586. if(pAMTuner) // load saved channel
  1587. {
  1588. pAMTuner->put_CountryCode(AfxGetApp()->GetProfileInt(_T("Capture"), _T("Country"), 1));
  1589. int vchannel = pODD->vchannel;
  1590. if(vchannel < 0) vchannel = AfxGetApp()->GetProfileInt(_T("Capture\") + CString(m_VidDispName), _T("Channel"), -1);
  1591. if(vchannel >= 0)
  1592. {
  1593. OAFilterState fs = State_Stopped;
  1594. pMC->GetState(0, &fs);
  1595. if(fs == State_Running) pMC->Pause();
  1596. pAMTuner->put_Channel(vchannel, AMTUNER_SUBCHAN_DEFAULT, AMTUNER_SUBCHAN_DEFAULT);
  1597. if(fs == State_Running) pMC->Run();
  1598. }
  1599. }
  1600. }
  1601. if(pAudCapTmp)
  1602. {
  1603. if(FAILED(hr = pGB->AddFilter(pAudCapTmp, CStringW(audfrname))))
  1604. {
  1605. throw _T("Can't add audio capture filter to the graph");
  1606. }
  1607. pAudCap = pAudCapTmp;
  1608. if(FAILED(pCGB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, pAudCap, IID_IAMStreamConfig, (void **)&pAMASC))
  1609. && FAILED(pCGB->FindInterface(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Audio, pAudCap, IID_IAMStreamConfig, (void **)&pAMASC)))
  1610. {
  1611. TRACE(_T("Warning: No IAMStreamConfig interface for vidcap"));
  1612. }
  1613. /*
  1614. CInterfaceArray<IAMAudioInputMixer> pAMAIM;
  1615. BeginEnumPins(pAudCap, pEP, pPin)
  1616. {
  1617. PIN_DIRECTION dir;
  1618. if(FAILED(pPin->QueryDirection(&dir)) || dir != PINDIR_INPUT)
  1619. continue;
  1620. if(CComQIPtr<IAMAudioInputMixer> pAIM = pPin) 
  1621. pAMAIM.Add(pAIM);
  1622. }
  1623. EndEnumPins
  1624. if(pAMASC)
  1625. {
  1626. m_wndCaptureBar.m_capdlg.SetupAudioControls(auddispname, pAMASC, pAMAIM);
  1627. }
  1628. */
  1629. }
  1630. if(!(pVidCap || pAudCap))
  1631. {
  1632. throw _T("Couldn't open any device");
  1633. }
  1634. pODD->title = _T("Live");
  1635. m_iPlaybackMode = PM_CAPTURE;
  1636. }
  1637. void CMainFrame::OpenCustomizeGraph()
  1638. {
  1639. if(m_iPlaybackMode == PM_CAPTURE)
  1640. return;
  1641. CleanGraph();
  1642. if(m_iPlaybackMode == PM_FILE)
  1643. {
  1644. if(m_pCAP)
  1645. AddTextPassThruFilter();
  1646. }
  1647. if(m_iPlaybackMode == PM_DVD)
  1648. {
  1649. BeginEnumFilters(pGB, pEF, pBF)
  1650. {
  1651. if(CComQIPtr<IDirectVobSub2> pDVS2 = pBF)
  1652. {
  1653. // pDVS2->AdviseSubClock(m_pSubClock = new CSubClock);
  1654. // break;
  1655. // TODO: test multiple dvobsub instances with one clock
  1656. if(!m_pSubClock) m_pSubClock = new CSubClock;
  1657. pDVS2->AdviseSubClock(m_pSubClock);
  1658. }
  1659. }
  1660. EndEnumFilters
  1661. }
  1662. BeginEnumFilters(pGB, pEF, pBF)
  1663. {
  1664. if(GetCLSID(pBF) == CLSID_OggSplitter)
  1665. {
  1666. if(CComQIPtr<IAMStreamSelect> pSS = pBF)
  1667. {
  1668. LCID idAudio = AfxGetAppSettings().idAudioLang;
  1669. if(!idAudio) idAudio = GetUserDefaultLCID();
  1670. LCID idSub = AfxGetAppSettings().idSubtitlesLang;
  1671. if(!idSub) idSub = GetUserDefaultLCID();
  1672. DWORD cnt = 0;
  1673. pSS->Count(&cnt);
  1674. for(DWORD i = 0; i < cnt; i++)
  1675. {
  1676. AM_MEDIA_TYPE* pmt = NULL;
  1677. DWORD dwFlags = 0;
  1678. LCID lcid = 0;
  1679. DWORD dwGroup = 0;
  1680. WCHAR* pszName = NULL;
  1681. if(SUCCEEDED(pSS->Info((long)i, &pmt, &dwFlags, &lcid, &dwGroup, &pszName, NULL, NULL)))
  1682. {
  1683. CStringW name(pszName), sound(L"Sound"), subtitle(L"Subtitle");
  1684. if(idAudio != -1 && (idAudio&0x3ff) == (lcid&0x3ff) // sublang seems to be zeroed out in ogm...
  1685. && name.GetLength() > sound.GetLength()
  1686. && !name.Left(sound.GetLength()).CompareNoCase(sound))
  1687. {
  1688. if(SUCCEEDED(pSS->Enable(i, AMSTREAMSELECTENABLE_ENABLE)))
  1689. idAudio = -1;
  1690. }
  1691. if(idSub != -1 && (idSub&0x3ff) == (lcid&0x3ff) // sublang seems to be zeroed out in ogm...
  1692. && name.GetLength() > subtitle.GetLength()
  1693. && !name.Left(subtitle.GetLength()).CompareNoCase(subtitle)
  1694. && name.Mid(subtitle.GetLength()).Trim().CompareNoCase(L"off"))
  1695. {
  1696. if(SUCCEEDED(pSS->Enable(i, AMSTREAMSELECTENABLE_ENABLE)))
  1697. idSub = -1;
  1698. }
  1699. if(pmt) DeleteMediaType(pmt);
  1700. if(pszName) CoTaskMemFree(pszName);
  1701. }
  1702. }
  1703. }
  1704. }
  1705. }
  1706. EndEnumFilters
  1707. CleanGraph();
  1708. }
  1709. void CMainFrame::OpenSetupVideo()
  1710. {
  1711. m_fAudioOnly = true;
  1712. if(m_pCAP)
  1713. {
  1714. CSize vs = m_pCAP->GetVideoSize();
  1715. m_fAudioOnly = (vs.cx <= 0 || vs.cy <= 0);
  1716. }
  1717. else
  1718. {
  1719. {
  1720. long w = 0, h = 0;
  1721. if(CComQIPtr<IBasicVideo> pBV = pGB)
  1722. {
  1723. pBV->GetVideoSize(&w, &h);
  1724. }
  1725. if(w > 0 && h > 0)
  1726. {
  1727. m_fAudioOnly = false;
  1728. }
  1729. }
  1730. if(m_fAudioOnly)
  1731. {
  1732. BeginEnumFilters(pGB, pEF, pBF)
  1733. {
  1734. long w = 0, h = 0;
  1735. if(CComQIPtr<IVideoWindow> pVW = pBF)
  1736. {
  1737. long lVisible;
  1738. if(FAILED(pVW->get_Visible(&lVisible)))
  1739. continue;
  1740. pVW->get_Width(&w);
  1741. pVW->get_Height(&h);
  1742. }
  1743. if(w > 0 && h > 0)
  1744. {
  1745. m_fAudioOnly = false;
  1746. break;
  1747. }
  1748. }
  1749. EndEnumFilters
  1750. }
  1751. }
  1752. if(m_fShockwaveGraph)
  1753. {
  1754. m_fAudioOnly = false;
  1755. }
  1756. if(!m_pCAP)
  1757. {
  1758. pVW->put_Owner((OAHWND)m_wndView.m_hWnd);
  1759. pVW->put_WindowStyle(WS_CHILD|WS_CLIPSIBLINGS|WS_CLIPCHILDREN);
  1760. pVW->put_MessageDrain((OAHWND)m_hWnd);
  1761. for(CWnd* pWnd = m_wndView.GetWindow(GW_CHILD); pWnd; pWnd = pWnd->GetNextWindow())
  1762. pWnd->EnableWindow(FALSE); // little trick to let WM_SETCURSOR thru
  1763. }
  1764. else
  1765. {
  1766. return;
  1767. /* char pSrcData[] = 
  1768. "sampler s0 : register(s0);rn"
  1769. "float4 p0 : register(c0);rn"
  1770. "rn"
  1771. "#define counter (p0[2])rn"
  1772. "#define clock (p0[3])rn"
  1773. "rn"
  1774. "float4 main(float2 t0 : TEXCOORD0) : COLORrn"
  1775. "{rn"
  1776. "tfloat4 c0 = tex2D(s0, t0);rn"
  1777. "tfloat3 lightsrc = float3(sin(clock*3.1415/3000)/2+0.5,cos(clock*3.1415/1000)/2+0.5,1);rn"
  1778. "tfloat3 light = normalize(lightsrc - float3(t0.x,t0.y,0));rn"
  1779. "tc0 *= pow(dot(light, float3(0,0,1)), 10);rn"
  1780. "treturn c0;rn"
  1781. "}rn";
  1782. //CComPtr<ID3DXBuffer> pErrorMsgs;
  1783. HRESULT hr = m_pCAP->SetPixelShader(pSrcData, "ps_2_0");
  1784. if(FAILED(hr))
  1785. {
  1786. CStringA err;
  1787. int len = pErrorMsgs->GetBufferSize();
  1788. memcpy(err.GetBufferSetLength(len), pErrorMsgs->GetBufferPointer(), len);
  1789. if(!err.IsEmpty()) AfxMessageBox(CString(err), MB_OK);
  1790. }
  1791. */
  1792. }
  1793. }
  1794. void CMainFrame::OpenSetupAudio()
  1795. {
  1796. pBA->put_Volume(m_wndToolBar.Volume);
  1797. // FIXME
  1798. int balance = AfxGetAppSettings().nBalance;
  1799. int sign = balance>0?-1:1;
  1800. balance = max(100-abs(balance), 1);
  1801. balance = (int)((log10(1.0*balance)-2)*5000*sign);
  1802. balance = max(min(balance, 10000), -10000);
  1803. pBA->put_Balance(balance);
  1804. }
  1805. /*
  1806. void CMainFrame::OpenSetupToolBar()
  1807. {
  1808. // m_wndToolBar.Volume = AfxGetAppSettings().nVolume;
  1809. // SetBalance(AfxGetAppSettings().nBalance);
  1810. }
  1811. */
  1812. void CMainFrame::OpenSetupCaptureBar()
  1813. {
  1814. if(m_iPlaybackMode == PM_CAPTURE)
  1815. {
  1816. if(pVidCap && pAMVSCCap) 
  1817. {
  1818.             CComQIPtr<IAMVfwCaptureDialogs> pVfwCD = pVidCap;
  1819. if(!pAMXBar && pVfwCD)
  1820. {
  1821. m_wndCaptureBar.m_capdlg.SetupVideoControls(m_VidDispName, pAMVSCCap, pVfwCD);
  1822. }
  1823. else
  1824. {
  1825. m_wndCaptureBar.m_capdlg.SetupVideoControls(m_VidDispName, pAMVSCCap, pAMXBar, pAMTuner);
  1826. }
  1827. }
  1828. if(pAudCap && pAMASC)
  1829. {
  1830. CInterfaceArray<IAMAudioInputMixer> pAMAIM;
  1831. BeginEnumPins(pAudCap, pEP, pPin)
  1832. {
  1833. PIN_DIRECTION dir;
  1834. if(FAILED(pPin->QueryDirection(&dir)) || dir != PINDIR_INPUT)
  1835. continue;
  1836. if(CComQIPtr<IAMAudioInputMixer> pAIM = pPin) 
  1837. pAMAIM.Add(pAIM);
  1838. }
  1839. EndEnumPins
  1840. m_wndCaptureBar.m_capdlg.SetupAudioControls(m_AudDispName, pAMASC, pAMAIM);
  1841. }
  1842. }
  1843. BuildGraphVideoAudio(
  1844. !!m_wndCaptureBar.m_capdlg.m_fVidPreview, false, 
  1845. !!m_wndCaptureBar.m_capdlg.m_fAudPreview, false);
  1846. }
  1847. void CMainFrame::OpenSetupInfoBar()
  1848. {
  1849. if(m_iPlaybackMode == PM_FILE)
  1850. {
  1851. bool fEmpty = true;
  1852. BeginEnumFilters(pGB, pEF, pBF)
  1853. {
  1854. if(CComQIPtr<IAMMediaContent, &IID_IAMMediaContent> pAMMC = pBF)
  1855. {
  1856. CComBSTR bstr;
  1857. if(SUCCEEDED(pAMMC->get_Title(&bstr))) {m_wndInfoBar.SetLine(_T("Title"), bstr.m_str); if(bstr.Length()) fEmpty = false;}
  1858. if(SUCCEEDED(pAMMC->get_AuthorName(&bstr))) {m_wndInfoBar.SetLine(_T("Author"), bstr.m_str); if(bstr.Length()) fEmpty = false;}
  1859. if(SUCCEEDED(pAMMC->get_Copyright(&bstr))) {m_wndInfoBar.SetLine(_T("Copyright"), bstr.m_str); if(bstr.Length()) fEmpty = false;}
  1860. if(SUCCEEDED(pAMMC->get_Rating(&bstr))) {m_wndInfoBar.SetLine(_T("Rating"), bstr.m_str); if(bstr.Length()) fEmpty = false;}
  1861. if(SUCCEEDED(pAMMC->get_Description(&bstr))) {m_wndInfoBar.SetLine(_T("Description"), bstr.m_str); if(bstr.Length()) fEmpty = false;}
  1862. if(!fEmpty)
  1863. {
  1864. RecalcLayout();
  1865. break;
  1866. }
  1867. }
  1868. }
  1869. EndEnumFilters
  1870. }
  1871. else if(m_iPlaybackMode == PM_DVD)
  1872. {
  1873. CString info('-');
  1874. m_wndInfoBar.SetLine(_T("Domain"), info);
  1875. m_wndInfoBar.SetLine(_T("Location"), info);
  1876. m_wndInfoBar.SetLine(_T("Video"), info);
  1877. m_wndInfoBar.SetLine(_T("Audio"), info);
  1878. m_wndInfoBar.SetLine(_T("Subtitles"), info);
  1879. RecalcLayout();
  1880. }
  1881. }
  1882. void CMainFrame::OpenSetupStatsBar()
  1883. {
  1884. CString info('-');
  1885. BeginEnumFilters(pGB, pEF, pBF)
  1886. {
  1887. if(!pQP && (pQP = pBF))
  1888. {
  1889. m_wndStatsBar.SetLine(_T("Frame-rate"), info);
  1890. m_wndStatsBar.SetLine(_T("Sync Offset"), info);
  1891. m_wndStatsBar.SetLine(_T("Frames"), info);
  1892. m_wndStatsBar.SetLine(_T("Jitter"), info);
  1893. m_wndStatsBar.SetLine(_T("Buffers"), info);
  1894. m_wndStatsBar.SetLine(_T("Bitrate"), info);
  1895. RecalcLayout();
  1896. }
  1897. if(!pBI && (pBI = pBF))
  1898. {
  1899. m_wndStatsBar.SetLine(_T("Buffers"), info);
  1900. m_wndStatsBar.SetLine(_T("Bitrate"), info); // FIXME: shouldn't be here
  1901. RecalcLayout();
  1902. }
  1903. }
  1904. EndEnumFilters
  1905. }
  1906. void CMainFrame::OpenSetupStatusBar()
  1907. {
  1908. m_wndStatusBar.ShowTimer(true);
  1909. //
  1910. if(!m_fCustomGraph)
  1911. {
  1912. UINT id = IDB_NOAUDIO;
  1913. BeginEnumFilters(pGB, pEF, pBF)
  1914. {
  1915. CComQIPtr<IBasicAudio> pBA = pBF;
  1916. if(!pBA) continue;
  1917. BeginEnumPins(pBF, pEP, pPin)
  1918. {
  1919. PIN_DIRECTION dir;
  1920. CComPtr<IPin> pPinTo;
  1921. if(S_OK == pPin->QueryDirection(&dir) && dir == PINDIR_INPUT
  1922. && S_OK == pPin->ConnectedTo(&pPinTo) && pPinTo)
  1923. {
  1924. AM_MEDIA_TYPE mt;
  1925. memset(&mt, 0, sizeof(mt));
  1926. pPin->ConnectionMediaType(&mt);
  1927. if(mt.majortype == MEDIATYPE_Audio 
  1928. && mt.formattype == FORMAT_WaveFormatEx)
  1929. {
  1930. switch(((WAVEFORMATEX*)mt.pbFormat)->nChannels)
  1931. {
  1932. case 1: id = IDB_MONO; break;
  1933. case 2: default: id = IDB_STEREO; break;
  1934. }
  1935. break;
  1936. }
  1937. else if(mt.majortype == MEDIATYPE_Midi)
  1938. {
  1939. id = NULL;
  1940. break;
  1941. }
  1942. }
  1943. }
  1944. EndEnumPins
  1945. if(id != IDB_NOAUDIO)
  1946. {
  1947. break;
  1948. }
  1949. }
  1950. EndEnumFilters
  1951. m_wndStatusBar.SetStatusBitmap(id);
  1952. }
  1953. //
  1954. HICON hIcon = NULL;
  1955. if(m_iPlaybackMode == PM_FILE)
  1956. {
  1957. CString fn = m_wndPlaylistBar.GetCur();
  1958. CString ext = fn.Mid(fn.ReverseFind('.')+1);
  1959. hIcon = LoadIcon(ext, true);
  1960. }
  1961. else if(m_iPlaybackMode == PM_DVD)
  1962. {
  1963. hIcon = LoadIcon(_T(".ifo"), true);
  1964. }
  1965. else if(m_iPlaybackMode == PM_DVD)
  1966. {
  1967. // hIcon = ; // TODO
  1968. }
  1969. m_wndStatusBar.SetStatusTypeIcon(hIcon);
  1970. }
  1971. void CMainFrame::OpenSetupWindowTitle(CString fn)
  1972. {
  1973. CString title(MAKEINTRESOURCE(IDR_MAINFRAME));
  1974. int i = AfxGetAppSettings().iTitleBarTextStyle;
  1975. if(!fn.IsEmpty() && (i == 0 || i == 1))
  1976. {
  1977. if(i == 1)
  1978. {
  1979. if(m_iPlaybackMode == PM_FILE)
  1980. {
  1981. fn.Replace('\', '/');
  1982. CString fn2 = fn.Mid(fn.ReverseFind('/')+1);
  1983. if(!fn2.IsEmpty()) fn = fn2;
  1984. }
  1985. else if(m_iPlaybackMode == PM_DVD)
  1986. {
  1987. fn = _T("DVD");
  1988. }
  1989. else if(m_iPlaybackMode == PM_CAPTURE)
  1990. {
  1991. fn = _T("Live");
  1992. }
  1993. }
  1994. title = fn + _T(" - ") + title;
  1995. }
  1996. SetWindowText(title);
  1997. }
  1998. bool CMainFrame::OpenMediaPrivate(CAutoPtr<OpenMediaData> pOMD)
  1999. {
  2000. if(m_iMediaLoadState != MLS_CLOSED)
  2001. {
  2002. ASSERT(0);
  2003. return(false);
  2004. }
  2005. if(!dynamic_cast<OpenFileData*>(pOMD.m_p)
  2006. && !dynamic_cast<OpenDVDData*>(pOMD.m_p)
  2007. && !dynamic_cast<OpenDeviceData*>(pOMD.m_p))
  2008. {
  2009. ASSERT(0);
  2010. return(false);
  2011. }
  2012. if(OpenFileData* pOFD = dynamic_cast<OpenFileData*>(pOMD.m_p))
  2013. {
  2014. if(pOFD->fns.IsEmpty())
  2015. return(false);
  2016. CString fn = pOFD->fns.GetHead();
  2017. int i = fn.Find(_T(":\"));
  2018. if(i > 0)
  2019. {
  2020. CString drive = fn.Left(i+2);
  2021. UINT type = GetDriveType(drive);
  2022. CList<CString> sl;
  2023. if(type == DRIVE_REMOVABLE || type == DRIVE_CDROM && GetCDROMType(drive[0], sl) != CDROM_Audio)
  2024. {
  2025. int ret = IDRETRY;
  2026. while(ret == IDRETRY)
  2027. {
  2028. WIN32_FIND_DATA findFileData;
  2029. HANDLE h = FindFirstFile(fn, &findFileData);
  2030. if(h != INVALID_HANDLE_VALUE)
  2031. {
  2032. FindClose(h);
  2033. ret = IDOK;
  2034. }
  2035. else
  2036. {
  2037. CString msg;
  2038. msg.Format(_T("%s was not found, please insert media containing this file."), fn);
  2039. ret = AfxMessageBox(msg, MB_RETRYCANCEL);
  2040. }
  2041. }
  2042. if(ret != IDOK)
  2043. return(false);
  2044. }
  2045. }
  2046. }
  2047. m_iMediaLoadState = MLS_LOADING;
  2048. // FIXME: Don't show "Closed" initially
  2049. PostMessage(WM_KICKIDLE);
  2050. CString err, aborted(_T("Aborted"));
  2051. m_fUpdateInfoBar = false;
  2052. try
  2053. {
  2054. if(m_fOpeningAborted) throw aborted;
  2055. OpenCreateGraphObject(pOMD);
  2056. AddToRot(pGB, &m_dwRegister);
  2057. if(m_fOpeningAborted) throw aborted;
  2058. SetupIViAudReg();
  2059. if(m_fOpeningAborted) throw aborted;
  2060. if(OpenFileData* p = dynamic_cast<OpenFileData*>(pOMD.m_p))
  2061. {
  2062. OpenFile(p);
  2063. }
  2064. else if(OpenDVDData* p = dynamic_cast<OpenDVDData*>(pOMD.m_p))
  2065. {
  2066. OpenDVD(p);
  2067. }
  2068. else if(OpenDeviceData* p = dynamic_cast<OpenDeviceData*>(pOMD.m_p))
  2069. {
  2070. OpenCapture(p);
  2071. }
  2072. else
  2073. {
  2074. throw _T("Can't open, invalid input parameters");
  2075. }
  2076. if(m_fOpeningAborted) throw aborted;
  2077. OpenCustomizeGraph();
  2078. if(m_fOpeningAborted) throw aborted;
  2079. OpenSetupVideo();
  2080. if(m_fOpeningAborted) throw aborted;
  2081. OpenSetupAudio();
  2082. if(m_fOpeningAborted) throw aborted;
  2083. if(m_pCAP && (!m_fAudioOnly || m_fRealMediaGraph))
  2084. {
  2085. POSITION pos = pOMD->subs.GetHeadPosition();
  2086. while(pos) LoadSubtitle(pOMD->subs.GetNext(pos));
  2087. if(m_pSubStreams.GetCount() > 0)
  2088. SetSubtitle(m_pSubStreams.GetHead());
  2089. }
  2090. if(m_fOpeningAborted) throw aborted;
  2091. OpenSetupWindowTitle(pOMD->title);
  2092. if(::GetCurrentThreadId() == AfxGetApp()->m_nThreadID)
  2093. {
  2094. OnFilePostOpenmedia();
  2095. }
  2096. else
  2097. {
  2098. PostMessage(WM_COMMAND, ID_FILE_POST_OPENMEDIA);
  2099. }
  2100. while(m_iMediaLoadState != MLS_LOADED 
  2101. && m_iMediaLoadState != MLS_CLOSING // FIXME
  2102. )
  2103. {
  2104. Sleep(50);
  2105. }
  2106. // PostMessage instead of SendMessage because the user might call CloseMedia and then we would deadlock
  2107. PostMessage(WM_COMMAND, ID_PLAY_PAUSE);
  2108. if(!(AfxGetAppSettings().nCLSwitches&CLSW_OPEN))
  2109. PostMessage(WM_COMMAND, ID_PLAY_PLAY);
  2110. AfxGetAppSettings().nCLSwitches &= ~CLSW_OPEN;
  2111. if(OpenFileData* p = dynamic_cast<OpenFileData*>(pOMD.m_p))
  2112. {
  2113. if(p->rtStart > 0)
  2114. PostMessage(WM_RESUMEFROMSTATE, (WPARAM)PM_FILE, (LPARAM)(p->rtStart/10000)); // REFERENCE_TIME doesn't fit in LPARAM under a 32bit env.
  2115. }
  2116. else if(OpenDVDData* p = dynamic_cast<OpenDVDData*>(pOMD.m_p))
  2117. {
  2118. if(p->pDvdState)
  2119. PostMessage(WM_RESUMEFROMSTATE, (WPARAM)PM_DVD, (LPARAM)(CComPtr<IDvdState>(p->pDvdState).Detach())); // must be released by the called message handler
  2120. }
  2121. else if(OpenDeviceData* p = dynamic_cast<OpenDeviceData*>(pOMD.m_p))
  2122. {
  2123. m_wndCaptureBar.m_capdlg.SetVideoInput(p->vinput);
  2124. m_wndCaptureBar.m_capdlg.SetVideoChannel(p->vchannel);
  2125. m_wndCaptureBar.m_capdlg.SetAudioInput(p->ainput);
  2126. }
  2127. }
  2128. catch(LPCTSTR msg)
  2129. {
  2130. err = msg;
  2131. }
  2132. catch(CString msg)
  2133. {
  2134. err = msg;
  2135. }
  2136. if(!err.IsEmpty())
  2137. {
  2138. CloseMediaPrivate();
  2139. m_closingmsg = err;
  2140. OpenFileData* p = dynamic_cast<OpenFileData*>(pOMD.m_p);
  2141. if(p && err != aborted)
  2142. {
  2143. m_wndPlaylistBar.SetCurValid(false);
  2144. if(m_wndPlaylistBar.GetCount() > 1)
  2145. {
  2146. CPlaylistItem pli[2];
  2147. m_wndPlaylistBar.GetCur(pli[0]);
  2148. m_wndPlaylistBar.SetNext();
  2149. m_wndPlaylistBar.GetCur(pli[1]);
  2150. if(pli[0].m_id != pli[1].m_id)
  2151. {
  2152. CAutoPtr<OpenMediaData> p(m_wndPlaylistBar.GetCurOMD());
  2153. if(p) OpenMediaPrivate(p);
  2154. }
  2155. }
  2156. }
  2157. }
  2158. else
  2159. {
  2160. m_wndPlaylistBar.SetCurValid(true);
  2161. }
  2162. PostMessage(WM_KICKIDLE); // calls main thread to update things
  2163. return(err.IsEmpty());
  2164. }
  2165. void CMainFrame::CloseMediaPrivate()
  2166. {
  2167. m_iMediaLoadState = MLS_CLOSING;
  2168.     OnPlayStop(); // SendMessage(WM_COMMAND, ID_PLAY_STOP);
  2169. m_iPlaybackMode = PM_NONE;
  2170. m_iSpeedLevel = 0;
  2171. m_fLiveWM = false;
  2172. m_fEndOfStream = false;
  2173. m_rtDurationOverride = -1;
  2174. m_kfs.RemoveAll();
  2175. m_pCB = NULL;
  2176. RemoveFromRot(m_dwRegister);
  2177. // if(pVW) pVW->put_Visible(OAFALSE);
  2178. // if(pVW) pVW->put_MessageDrain((OAHWND)NULL), pVW->put_Owner((OAHWND)NULL);
  2179. m_pCAP = NULL; // IMPORTANT: IVMRSurfaceAllocatorNotify/IVMRSurfaceAllocatorNotify9 has to be released before the VMR/VMR9, otherwise it will crash in Release()
  2180. m_shaderlabel.Empty();
  2181. pAMXBar.Release(); pAMTuner.Release(); pAMDF.Release();
  2182. pAMVCCap.Release(); pAMVCPrev.Release(); pAMVSCCap.Release(); pAMVSCPrev.Release(); pAMASC.Release();
  2183. pVidCap.Release(); pAudCap.Release();
  2184. pCGB.Release();
  2185. pVMR.Release();
  2186. pDVDC.Release(); pDVDI.Release();
  2187. pQP.Release(); pBI.Release(); pAMOP.Release(); pFS.Release();
  2188. pMC.Release(); pME.Release(); pMS.Release();
  2189. pVW.Release(); pBV.Release();
  2190. pBA.Release();
  2191. pGB.Release();
  2192. m_fRealMediaGraph = m_fShockwaveGraph = m_fQuicktimeGraph = false;
  2193. m_pSubClock = NULL;
  2194. m_pProv.Release();
  2195. {
  2196. CAutoLock cAutoLock(&m_csSubLock);
  2197. m_pSubStreams.RemoveAll();
  2198. }
  2199. m_VidDispName.Empty();
  2200. m_AudDispName.Empty();
  2201. m_closingmsg = _T("Closed");
  2202. AfxGetAppSettings().nCLSwitches &= CLSW_OPEN|CLSW_PLAY|CLSW_AFTERPLAYBACK_MASK|CLSW_NOFOCUS;
  2203. m_iMediaLoadState = MLS_CLOSED;
  2204. }
  2205. // msn
  2206. void CMainFrame::SendNowPlayingToMSN()
  2207. {
  2208. if(!AfxGetAppSettings().fNotifyMSN)
  2209. return;
  2210. CString title, author;
  2211. if(m_iMediaLoadState == MLS_LOADED)
  2212. {
  2213. m_wndInfoBar.GetLine(_T("Title"), title);
  2214. m_wndInfoBar.GetLine(_T("Author"), author);
  2215. if(title.IsEmpty())
  2216. {
  2217. CPlaylistItem pli;
  2218. m_wndPlaylistBar.GetCur(pli);
  2219. if(!pli.m_fns.IsEmpty())
  2220. {
  2221. CString label = !pli.m_label.IsEmpty() ? pli.m_label : pli.m_fns.GetHead();
  2222. if(m_iPlaybackMode == PM_FILE)
  2223. {
  2224. CString fn = label;
  2225. if(fn.Find(_T("://")) >= 0) {int i = fn.Find('?'); if(i >= 0) fn = fn.Left(i);}
  2226. CPath path(fn);
  2227. path.StripPath();
  2228. path.MakePretty();
  2229. path.RemoveExtension();
  2230. title = (LPCTSTR)path;
  2231. author.Empty();
  2232. }
  2233. else if(m_iPlaybackMode == PM_CAPTURE)
  2234. {
  2235. title = label != pli.m_fns.GetHead() ? label : _T("Live");
  2236. author.Empty();
  2237. }
  2238. else if(m_iPlaybackMode == PM_DVD)
  2239. {
  2240. title = _T("DVD");
  2241. author.Empty();
  2242. }
  2243. }
  2244. }
  2245. }
  2246. CStringW buff;
  2247. buff += L"\0Music\0";
  2248. buff += title.IsEmpty() ? L"0" : L"1";
  2249. buff += L"\0";
  2250. buff += author.IsEmpty() ? L"{0}" : L"{0} - {1}";
  2251. buff += L"\0";
  2252. if(!author.IsEmpty()) {buff += CStringW(author) + L"\0";}
  2253. buff += CStringW(title) + L"\0";
  2254. buff += L"\0\0";
  2255. COPYDATASTRUCT data;
  2256.     data.dwData = 0x0547;
  2257.     data.lpData = (PVOID)(LPCWSTR)buff;
  2258.     data.cbData = buff.GetLength() * 2 + 2;
  2259. HWND hWnd = NULL;
  2260. while(hWnd = ::FindWindowEx(NULL, hWnd, _T("MsnMsgrUIManager"), NULL))
  2261. ::SendMessage(hWnd, WM_COPYDATA, (WPARAM)NULL, (LPARAM)&data);
  2262. }
  2263. // dynamic menus
  2264. void CMainFrame::SetupOpenCDSubMenu()
  2265. {
  2266. CMenu* pSub = &m_opencds;
  2267. if(!IsMenu(pSub->m_hMenu)) pSub->CreatePopupMenu();
  2268. else while(pSub->RemoveMenu(0, MF_BYPOSITION));
  2269. if(m_iMediaLoadState == MLS_LOADING) return;
  2270. if(AfxGetAppSettings().fHideCDROMsSubMenu) return;
  2271. UINT id = ID_FILE_OPEN_CD_START;
  2272. for(TCHAR drive = 'C'; drive <= 'Z'; drive++)
  2273. {
  2274. CString label = GetDriveLabel(drive), str;
  2275. CList<CString> files;
  2276. switch(GetCDROMType(drive, files))
  2277. {
  2278. case CDROM_Audio:
  2279. if(label.IsEmpty()) label = _T("Audio CD");
  2280. str.Format(_T("%s (%c:)"), label, drive);
  2281. break;
  2282. case CDROM_VideoCD:
  2283. if(label.IsEmpty()) label = _T("(S)VCD");
  2284. str.Format(_T("%s (%c:)"), label, drive);
  2285. break;
  2286. case CDROM_DVDVideo:
  2287. if(label.IsEmpty()) label = _T("DVD Video");
  2288. str.Format(_T("%s (%c:)"), label, drive);
  2289. break;
  2290. default:
  2291. break;
  2292. }
  2293. if(!str.IsEmpty())
  2294. pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, str);
  2295. }
  2296. }
  2297. void CMainFrame::SetupFiltersSubMenu()
  2298. {
  2299. CMenu* pSub = &m_filters;
  2300. if(!IsMenu(pSub->m_hMenu)) pSub->CreatePopupMenu();
  2301. else while(pSub->RemoveMenu(0, MF_BYPOSITION));
  2302. m_filterpopups.RemoveAll();
  2303. m_spparray.RemoveAll();
  2304. m_ssarray.RemoveAll();
  2305. if(m_iMediaLoadState == MLS_LOADED)
  2306. {
  2307. UINT idf = 0;
  2308. UINT ids = ID_FILTERS_SUBITEM_START;
  2309. UINT idl = ID_FILTERSTREAMS_SUBITEM_START;
  2310. BeginEnumFilters(pGB, pEF, pBF)
  2311. {
  2312. CString name(GetFilterName(pBF));
  2313. if(name.GetLength() >= 43) name = name.Left(40) + _T("...");
  2314. CLSID clsid = GetCLSID(pBF);
  2315. if(clsid == CLSID_AVIDec)
  2316. {
  2317. CComPtr<IPin> pPin = GetFirstPin(pBF);
  2318. AM_MEDIA_TYPE mt;
  2319. if(pPin && SUCCEEDED(pPin->ConnectionMediaType(&mt)))
  2320. {
  2321. DWORD c = ((VIDEOINFOHEADER*)mt.pbFormat)->bmiHeader.biCompression;
  2322. switch(c)
  2323. {
  2324. case BI_RGB: name += _T(" (RGB)"); break;
  2325. case BI_RLE4: name += _T(" (RLE4)"); break;
  2326. case BI_RLE8: name += _T(" (RLE8)"); break;
  2327. case BI_BITFIELDS: name += _T(" (BITF)"); break;
  2328. default: name.Format(_T("%s (%c%c%c%c)"), 
  2329.  CString(name), (TCHAR)((c>>0)&0xff), (TCHAR)((c>>8)&0xff), (TCHAR)((c>>16)&0xff), (TCHAR)((c>>24)&0xff)); break;
  2330. }
  2331. }
  2332. }
  2333. else if(clsid == CLSID_ACMWrapper)
  2334. {
  2335. CComPtr<IPin> pPin = GetFirstPin(pBF);
  2336. AM_MEDIA_TYPE mt;
  2337. if(pPin && SUCCEEDED(pPin->ConnectionMediaType(&mt)))
  2338. {
  2339. WORD c = ((WAVEFORMATEX*)mt.pbFormat)->wFormatTag;
  2340. name.Format(_T("%s (0x%04x)"), CString(name), (int)c);
  2341. }
  2342. }
  2343. else if(clsid == __uuidof(CTextPassThruFilter) || clsid == __uuidof(CNullTextRenderer)
  2344. || clsid == GUIDFromCString(_T("{48025243-2D39-11CE-875D-00608CB78066}"))) // ISCR
  2345. {
  2346. // hide these
  2347. continue;
  2348. }
  2349. CAutoPtr<CMenu> pSubSub(new CMenu);
  2350. pSubSub->CreatePopupMenu();
  2351. int nPPages = 0;
  2352. CComQIPtr<ISpecifyPropertyPages> pSPP = pBF;
  2353. if(pSPP)
  2354. {
  2355. CAUUID caGUID;
  2356. caGUID.pElems = NULL;
  2357. if(SUCCEEDED(pSPP->GetPages(&caGUID)) && caGUID.cElems > 0)
  2358. {
  2359. m_spparray.Add(pSPP);
  2360. pSubSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, ids, _T("&Properties..."));
  2361. if(caGUID.pElems) CoTaskMemFree(caGUID.pElems);
  2362. nPPages++;
  2363. }
  2364. }
  2365. BeginEnumPins(pBF, pEP, pPin)
  2366. {
  2367. CString name = GetPinName(pPin);
  2368. name.Replace(_T("&"), _T("&&"));
  2369. if(pSPP = pPin)
  2370. {
  2371. CAUUID caGUID;
  2372. caGUID.pElems = NULL;
  2373. if(SUCCEEDED(pSPP->GetPages(&caGUID)) && caGUID.cElems > 0)
  2374. {
  2375. m_spparray.Add(pSPP);
  2376. pSubSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, ids+nPPages, name + _T(" (pin) properties..."));
  2377. if(caGUID.pElems) CoTaskMemFree(caGUID.pElems);
  2378. nPPages++;
  2379. }
  2380. }
  2381. }
  2382. EndEnumPins
  2383. CComQIPtr<IAMStreamSelect> pSS = pBF;
  2384. if(pSS)
  2385. {
  2386. DWORD nStreams = 0, flags, group, prevgroup = -1;
  2387. LCID lcid;
  2388. WCHAR* wname = NULL;
  2389. CComPtr<IUnknown> pObj, pUnk;
  2390. pSS->Count(&nStreams);
  2391. if(nStreams > 0 && nPPages > 0) pSubSub->AppendMenu(MF_SEPARATOR|MF_ENABLED);
  2392. UINT idlstart = idl;
  2393. for(DWORD i = 0; i < nStreams; i++, pObj = NULL, pUnk = NULL)
  2394. {
  2395. m_ssarray.Add(pSS);
  2396. flags = group = 0;
  2397. wname = NULL;
  2398. pSS->Info(i, NULL, &flags, &lcid, &group, &wname, &pObj, &pUnk);
  2399. if(group != prevgroup && idl > idlstart)
  2400. pSubSub->AppendMenu(MF_SEPARATOR|MF_ENABLED);
  2401. prevgroup = group;
  2402. if(flags & AMSTREAMSELECTINFO_EXCLUSIVE)
  2403. {
  2404. }
  2405. else if(flags & AMSTREAMSELECTINFO_ENABLED)
  2406. {
  2407. }
  2408. if(!wname) 
  2409. {
  2410. CStringW stream(L"Unknown Stream");
  2411. wname = (WCHAR*)CoTaskMemAlloc((stream.GetLength()+3+1)*sizeof(WCHAR));
  2412. swprintf(wname, L"%s %d", stream, min(i+1,999));
  2413. }
  2414. CString name(wname);
  2415. name.Replace(_T("&"), _T("&&"));
  2416. pSubSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, idl++, name);
  2417. CoTaskMemFree(wname);
  2418. }
  2419. if(nStreams == 0) pSS.Release();
  2420. }
  2421. if(nPPages == 1 && !pSS)
  2422. {
  2423. pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, ids, name);
  2424. }
  2425. else 
  2426. {
  2427. pSub->AppendMenu(MF_BYPOSITION|MF_STRING|MF_DISABLED|MF_GRAYED, idf, name);
  2428. if(nPPages > 0 || pSS)
  2429. {
  2430. MENUITEMINFO mii;
  2431. mii.cbSize = sizeof(mii);
  2432. mii.fMask = MIIM_STATE|MIIM_SUBMENU;
  2433. mii.fType = MF_POPUP;
  2434. mii.hSubMenu = pSubSub->m_hMenu;
  2435. mii.fState = (pSPP || pSS) ? MF_ENABLED : (MF_DISABLED|MF_GRAYED);
  2436. pSub->SetMenuItemInfo(idf, &mii, TRUE);
  2437. m_filterpopups.Add(pSubSub);
  2438. }
  2439. }
  2440. ids += nPPages;
  2441. idf++;
  2442. }
  2443. EndEnumFilters
  2444. }
  2445. }
  2446. void CMainFrame::SetupAudioSwitcherSubMenu()
  2447. {
  2448. CMenu* pSub = &m_audios;
  2449. if(!IsMenu(pSub->m_hMenu)) pSub->CreatePopupMenu();
  2450. else while(pSub->RemoveMenu(0, MF_BYPOSITION));
  2451. if(m_iMediaLoadState == MLS_LOADED)
  2452. {
  2453. UINT id = ID_AUDIO_SUBITEM_START;
  2454. CComQIPtr<IAMStreamSelect> pSS = FindFilter(__uuidof(CAudioSwitcherFilter), pGB);
  2455. if(!pSS) pSS = FindFilter(L"{D3CD7858-971A-4838-ACEC-40CA5D529DC8}", pGB);
  2456. if(pSS)
  2457. {
  2458. DWORD cStreams = 0;
  2459. if(SUCCEEDED(pSS->Count(&cStreams)) && cStreams > 0)
  2460. {
  2461. pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, _T("&Options..."));
  2462. pSub->AppendMenu(MF_SEPARATOR|MF_ENABLED);
  2463. for(int i = 0; i < (int)cStreams; i++)
  2464. {
  2465. WCHAR* pName = NULL;
  2466. if(FAILED(pSS->Info(i, NULL, NULL, NULL, NULL, &pName, NULL, NULL)))
  2467. break;
  2468. CString name(pName);
  2469. name.Replace(_T("&"), _T("&&"));
  2470. pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, name);
  2471. CoTaskMemFree(pName);
  2472. }
  2473. }
  2474. }
  2475. }
  2476. }
  2477. void CMainFrame::SetupSubtitlesSubMenu()
  2478. {
  2479. CMenu* pSub = &m_subtitles;
  2480. if(!IsMenu(pSub->m_hMenu)) pSub->CreatePopupMenu();
  2481. else while(pSub->RemoveMenu(0, MF_BYPOSITION));
  2482. if(m_iMediaLoadState != MLS_LOADED || m_fAudioOnly || !m_pCAP)
  2483. return;
  2484. UINT id = ID_SUBTITLES_SUBITEM_START;
  2485. POSITION pos = m_pSubStreams.GetHeadPosition();
  2486. if(pos)
  2487. {
  2488. pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, _T("&Options..."));
  2489. pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, _T("&Styles..."));
  2490. pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, _T("&Reload"));
  2491. pSub->AppendMenu(MF_SEPARATOR);
  2492. pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, _T("&Enable"));
  2493. pSub->AppendMenu(MF_SEPARATOR);
  2494. }
  2495. while(pos)
  2496. {
  2497. CComPtr<ISubStream> pSubStream = m_pSubStreams.GetNext(pos);
  2498. if(!pSubStream) continue;
  2499. for(int i = 0, j = pSubStream->GetStreamCount(); i < j; i++)
  2500. {
  2501. WCHAR* pName = NULL;
  2502. if(SUCCEEDED(pSubStream->GetStreamInfo(i, &pName, NULL)))
  2503. {
  2504. CString name(pName);
  2505. name.Replace(_T("&"), _T("&&"));
  2506. pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, name);
  2507. CoTaskMemFree(pName);
  2508. }
  2509. else
  2510. {
  2511. pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, id++, _T("<Unknown>"));
  2512. }
  2513. }
  2514. // TODO: find a better way to group these entries
  2515. if(pos && m_pSubStreams.GetAt(pos))
  2516. {
  2517. CLSID cur, next;
  2518. pSubStream->GetClassID(&cur);
  2519. m_pSubStreams.GetAt(pos)->GetClassID(&next);
  2520. if(cur != next)
  2521. pSub->AppendMenu(MF_SEPARATOR);
  2522. }
  2523. }
  2524. }
  2525. void CMainFrame::SetupNavAudioSubMenu()
  2526. {
  2527. CMenu* pSub = &m_navaudio;
  2528. if(!IsMenu(pSub->m_hMenu)) pSub->CreatePopupMenu();
  2529. else while(pSub->RemoveMenu(0, MF_BYPOSITION));
  2530. if(m_iMediaLoadState != MLS_LOADED) return;
  2531. UINT id = ID_NAVIGATE_AUDIO_SUBITEM_START;
  2532. if(m_iPlaybackMode == PM_FILE)
  2533. {
  2534. SetupNavStreamSelectSubMenu(pSub, id, 1);
  2535. }
  2536. else if(m_iPlaybackMode == PM_DVD)
  2537. {
  2538. ULONG ulStreamsAvailable, ulCurrentStream;
  2539. if(FAILED(pDVDI->GetCurrentAudio(&ulStreamsAvailable, &ulCurrentStream)))
  2540. return;
  2541. LCID DefLanguage;
  2542. DVD_AUDIO_LANG_EXT ext;
  2543. if(FAILED(pDVDI->GetDefaultAudioLanguage(&DefLanguage, &ext)))
  2544. return;
  2545.         for(ULONG i = 0; i < ulStreamsAvailable; i++)
  2546. {
  2547. LCID Language;
  2548. if(FAILED(pDVDI->GetAudioLanguage(i, &Language)))
  2549. continue;
  2550. UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
  2551. if(Language == DefLanguage) flags |= MF_DEFAULT;
  2552.             if(i == ulCurrentStream) flags |= MF_CHECKED;
  2553. CString str(_T("Unknown"));
  2554. if(Language)
  2555. {
  2556. int len = GetLocaleInfo(Language, LOCALE_SENGLANGUAGE, str.GetBuffer(256), 256);
  2557. str.ReleaseBufferSetLength(max(len-1, 0));
  2558. }
  2559. DVD_AudioAttributes ATR;
  2560. if(SUCCEEDED(pDVDI->GetAudioAttributes(i, &ATR)))
  2561. {
  2562. switch(ATR.LanguageExtension)
  2563. {
  2564. case DVD_AUD_EXT_NotSpecified:
  2565. default: break;
  2566. case DVD_AUD_EXT_Captions: str += _T(" (Captions)"); break;
  2567. case DVD_AUD_EXT_VisuallyImpaired: str += _T(" (Visually Impaired)"); break;
  2568. case DVD_AUD_EXT_DirectorComments1: str += _T(" (Director Comments 1)"); break;
  2569. case DVD_AUD_EXT_DirectorComments2: str += _T(" (Director Comments 2)"); break;
  2570. }
  2571. }
  2572. str.Replace(_T("&"), _T("&&"));
  2573. pSub->AppendMenu(flags, id++, str);
  2574. }
  2575. }
  2576. }
  2577. void CMainFrame::SetupNavSubtitleSubMenu()
  2578. {
  2579. CMenu* pSub = &m_navsubtitle;
  2580. if(!IsMenu(pSub->m_hMenu)) pSub->CreatePopupMenu();
  2581. else while(pSub->RemoveMenu(0, MF_BYPOSITION));
  2582. if(m_iMediaLoadState != MLS_LOADED) return;
  2583. UINT id = ID_NAVIGATE_SUBP_SUBITEM_START;
  2584. if(m_iPlaybackMode == PM_FILE)
  2585. {
  2586. SetupNavStreamSelectSubMenu(pSub, id, 2);
  2587. }
  2588. else if(m_iPlaybackMode == PM_DVD)
  2589. {
  2590. ULONG ulStreamsAvailable, ulCurrentStream;
  2591. BOOL bIsDisabled;
  2592. if(FAILED(pDVDI->GetCurrentSubpicture(&ulStreamsAvailable, &ulCurrentStream, &bIsDisabled))
  2593. || ulStreamsAvailable == 0)
  2594. return;
  2595. LCID DefLanguage;
  2596. DVD_SUBPICTURE_LANG_EXT ext;
  2597. if(FAILED(pDVDI->GetDefaultSubpictureLanguage(&DefLanguage, &ext)))
  2598. return;
  2599. pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|(bIsDisabled?0:MF_CHECKED), id++, _T("Enabled"));
  2600. pSub->AppendMenu(MF_BYCOMMAND|MF_SEPARATOR|MF_ENABLED);
  2601.         for(ULONG i = 0; i < ulStreamsAvailable; i++)
  2602. {
  2603. LCID Language;
  2604. if(FAILED(pDVDI->GetSubpictureLanguage(i, &Language)))
  2605. continue;
  2606. UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
  2607. if(Language == DefLanguage) flags |= MF_DEFAULT;
  2608.             if(i == ulCurrentStream) flags |= MF_CHECKED;
  2609. CString str(_T("Unknown"));
  2610. if(Language)
  2611. {
  2612. int len = GetLocaleInfo(Language, LOCALE_SENGLANGUAGE, str.GetBuffer(256), 256);
  2613. str.ReleaseBufferSetLength(max(len-1, 0));
  2614. }
  2615. DVD_SubpictureAttributes ATR;
  2616. if(SUCCEEDED(pDVDI->GetSubpictureAttributes(i, &ATR)))
  2617. {
  2618. switch(ATR.LanguageExtension)
  2619. {
  2620. case DVD_SP_EXT_NotSpecified:
  2621. default: break;
  2622. case DVD_SP_EXT_Caption_Normal: str += _T(""); break;
  2623. case DVD_SP_EXT_Caption_Big: str += _T(" (Big)"); break;
  2624. case DVD_SP_EXT_Caption_Children: str += _T(" (Children)"); break;
  2625. case DVD_SP_EXT_CC_Normal: str += _T(" (CC)"); break;
  2626. case DVD_SP_EXT_CC_Big: str += _T(" (CC Big)"); break;
  2627. case DVD_SP_EXT_CC_Children: str += _T(" (CC Children)"); break;
  2628. case DVD_SP_EXT_Forced: str += _T(" (Forced)"); break;
  2629. case DVD_SP_EXT_DirectorComments_Normal: str += _T(" (Director Comments)"); break;
  2630. case DVD_SP_EXT_DirectorComments_Big: str += _T(" (Director Comments, Big)"); break;
  2631. case DVD_SP_EXT_DirectorComments_Children: str += _T(" (Director Comments, Children)"); break;
  2632. }
  2633. }
  2634. str.Replace(_T("&"), _T("&&"));
  2635. pSub->AppendMenu(flags, id++, str);
  2636. }
  2637. }
  2638. }
  2639. void CMainFrame::SetupNavAngleSubMenu()
  2640. {
  2641. CMenu* pSub = &m_navangle;
  2642. if(!IsMenu(pSub->m_hMenu)) pSub->CreatePopupMenu();
  2643. else while(pSub->RemoveMenu(0, MF_BYPOSITION));
  2644. if(m_iMediaLoadState != MLS_LOADED) return;
  2645. UINT id = ID_NAVIGATE_ANGLE_SUBITEM_START;
  2646. if(m_iPlaybackMode == PM_FILE)
  2647. {
  2648. SetupNavStreamSelectSubMenu(pSub, id, 0);
  2649. }
  2650. else if(m_iPlaybackMode == PM_DVD)
  2651. {
  2652. ULONG ulStreamsAvailable, ulCurrentStream;
  2653. if(FAILED(pDVDI->GetCurrentAngle(&ulStreamsAvailable, &ulCurrentStream)))
  2654. return;
  2655. if(ulStreamsAvailable < 2) return; // one choice is not a choice...
  2656.         for(ULONG i = 0; i < ulStreamsAvailable; i++)
  2657. {
  2658. UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
  2659.             if(i == ulCurrentStream) flags |= MF_CHECKED;
  2660. CString str;
  2661. str.Format(_T("Angle %d"), i+1);
  2662. pSub->AppendMenu(flags, id++, str);
  2663. }
  2664. }
  2665. }
  2666. void CMainFrame::SetupNavChaptersSubMenu()
  2667. {
  2668. CMenu* pSub = &m_navchapters;
  2669. if(!IsMenu(pSub->m_hMenu)) pSub->CreatePopupMenu();
  2670. else while(pSub->RemoveMenu(0, MF_BYPOSITION));
  2671. if(m_iMediaLoadState != MLS_LOADED)
  2672. return;
  2673. UINT id = ID_NAVIGATE_CHAP_SUBITEM_START;
  2674. if(m_iPlaybackMode == PM_FILE)
  2675. {
  2676. SetupChapters();
  2677. REFERENCE_TIME rt = GetPos();
  2678. DWORD j = m_pCB->ChapLookup(&rt, NULL);
  2679. for(DWORD i = 0; i < m_pCB->ChapGetCount(); i++, id++)
  2680. {
  2681. rt = 0;
  2682. CComBSTR bstr;
  2683. if(FAILED(m_pCB->ChapGet(i, &rt, &bstr)))
  2684. continue;
  2685. int s = (int)((rt/10000000)%60);
  2686. int m = (int)((rt/10000000/60)%60);
  2687. int h = (int)((rt/10000000/60/60));
  2688. CString time;
  2689. time.Format(_T("[%02d:%02d:%02d] "), h, m, s);
  2690. CString name = CString(bstr);
  2691. name.Replace(_T("&"), _T("&&"));
  2692. name.Replace(_T("t"), _T(" "));
  2693. UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
  2694. if(i == j) flags |= MF_CHECKED;
  2695. if(id != ID_NAVIGATE_CHAP_SUBITEM_START && i == 0) pSub->AppendMenu(MF_SEPARATOR);
  2696. pSub->AppendMenu(flags, id, name + 't' + time);
  2697. }
  2698. if(m_wndPlaylistBar.GetCount() > 1)
  2699. {
  2700. POSITION pos = m_wndPlaylistBar.m_pl.GetHeadPosition();
  2701. while(pos)
  2702. {
  2703. UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
  2704. if(pos == m_wndPlaylistBar.m_pl.GetPos()) flags |= MF_CHECKED;
  2705. if(id != ID_NAVIGATE_CHAP_SUBITEM_START && pos == m_wndPlaylistBar.m_pl.GetHeadPosition())
  2706. pSub->AppendMenu(MF_SEPARATOR);
  2707. CPlaylistItem& pli = m_wndPlaylistBar.m_pl.GetNext(pos);
  2708. CString name = pli.GetLabel();
  2709. name.Replace(_T("&"), _T("&&"));
  2710. pSub->AppendMenu(flags, id++, name);
  2711. }
  2712. }
  2713. }
  2714. else if(m_iPlaybackMode == PM_DVD)
  2715. {
  2716. ULONG ulNumOfVolumes, ulVolume;
  2717. DVD_DISC_SIDE Side;
  2718. ULONG ulNumOfTitles = 0;
  2719. pDVDI->GetDVDVolumeInfo(&ulNumOfVolumes, &ulVolume, &Side, &ulNumOfTitles);
  2720. DVD_PLAYBACK_LOCATION2 Location;
  2721. pDVDI->GetCurrentLocation(&Location);
  2722. ULONG ulNumOfChapters = 0;
  2723. pDVDI->GetNumberOfChapters(Location.TitleNum, &ulNumOfChapters);
  2724. ULONG ulUOPs = 0;
  2725. pDVDI->GetCurrentUOPS(&ulUOPs);
  2726. for(ULONG i = 1; i <= ulNumOfTitles; i++)
  2727. {
  2728. UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
  2729. if(i == Location.TitleNum) flags |= MF_CHECKED;
  2730. if(ulUOPs&UOP_FLAG_Play_Title) flags |= MF_DISABLED|MF_GRAYED;
  2731. CString str;
  2732. str.Format(_T("Title %d"), i);
  2733. pSub->AppendMenu(flags, id++, str);
  2734. }
  2735. for(ULONG i = 1; i <= ulNumOfChapters; i++)
  2736. {
  2737. UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
  2738. if(i == Location.ChapterNum) flags |= MF_CHECKED;
  2739. if(ulUOPs&UOP_FLAG_Play_Chapter) flags |= MF_DISABLED|MF_GRAYED;
  2740. if(i == 1) flags |= MF_MENUBARBREAK;
  2741. CString str;
  2742. str.Format(_T("Chapter %d"), i);
  2743. pSub->AppendMenu(flags, id++, str);
  2744. }
  2745. }
  2746. }
  2747. void CMainFrame::SetupNavStreamSelectSubMenu(CMenu* pSub, UINT id, DWORD dwSelGroup)
  2748. {
  2749. UINT baseid = id;
  2750. CComQIPtr<IAMStreamSelect> pSS = FindFilter(CLSID_OggSplitter, pGB);
  2751. if(!pSS) pSS = FindFilter(L"{55DA30FC-F16B-49fc-BAA5-AE59FC65F82D}", pGB);
  2752. if(!pSS) return;
  2753. DWORD cStreams;
  2754. if(FAILED(pSS->Count(&cStreams)))
  2755. return;
  2756. DWORD dwPrevGroup = -1;
  2757. for(int i = 0, j = cStreams; i < j; i++)
  2758. {
  2759. DWORD dwFlags, dwGroup;
  2760. LCID lcid;
  2761. WCHAR* pszName = NULL;
  2762. if(FAILED(pSS->Info(i, NULL, &dwFlags, &lcid, &dwGroup, &pszName, NULL, NULL))
  2763. || !pszName)
  2764. continue;
  2765. CStringW name(pszName);
  2766. name.MakeLower();
  2767. if(pszName) CoTaskMemFree(pszName);
  2768. if(dwGroup != dwSelGroup)
  2769. continue;
  2770. if(dwPrevGroup != -1 && dwPrevGroup != dwGroup)
  2771. pSub->AppendMenu(MF_SEPARATOR);
  2772. dwPrevGroup = dwGroup;
  2773. CString str;
  2774. if(name.Find(L" off") >= 0)
  2775. {
  2776. str = _T("Disabled");
  2777. }
  2778. else if(lcid == 0)
  2779. {
  2780. str.Format(_T("Unknown %d"), id - baseid);
  2781. }
  2782. else
  2783. {
  2784. int len = GetLocaleInfo(lcid, LOCALE_SENGLANGUAGE, str.GetBuffer(64), 64);
  2785. str.ReleaseBufferSetLength(max(len-1, 0));
  2786. }
  2787. UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
  2788. if(dwFlags) flags |= MF_CHECKED;
  2789. str.Replace(_T("&"), _T("&&"));
  2790. pSub->AppendMenu(flags, id++, str);
  2791. }
  2792. }
  2793. void CMainFrame::OnNavStreamSelectSubMenu(UINT id, DWORD dwSelGroup)
  2794. {
  2795. CComQIPtr<IAMStreamSelect> pSS = FindFilter(CLSID_OggSplitter, pGB);
  2796. if(!pSS) pSS = FindFilter(L"{55DA30FC-F16B-49fc-BAA5-AE59FC65F82D}", pGB);
  2797. if(!pSS) return;
  2798. DWORD cStreams;
  2799. if(FAILED(pSS->Count(&cStreams)))
  2800. return;
  2801. for(int i = 0, j = cStreams; i < j; i++)
  2802. {
  2803. DWORD dwFlags, dwGroup;
  2804. LCID lcid;
  2805. WCHAR* pszName = NULL;
  2806. if(FAILED(pSS->Info(i, NULL, &dwFlags, &lcid, &dwGroup, &pszName, NULL, NULL))
  2807. || !pszName)
  2808. continue;
  2809. if(pszName) CoTaskMemFree(pszName);
  2810. if(dwGroup != dwSelGroup)
  2811. continue;
  2812. if(id == 0)
  2813. {
  2814. pSS->Enable(i, AMSTREAMSELECTENABLE_ENABLE);
  2815. break;
  2816. }
  2817. id--;
  2818. }
  2819. }
  2820. void CMainFrame::SetupFavoritesSubMenu()
  2821. {
  2822. CMenu* pSub = &m_favorites;
  2823. if(!IsMenu(pSub->m_hMenu)) pSub->CreatePopupMenu();
  2824. else while(pSub->RemoveMenu(0, MF_BYPOSITION));
  2825. AppSettings& s = AfxGetAppSettings();
  2826. pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, ID_FAVORITES_ADD, _T("&Add to Favorites..."));
  2827. pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, ID_FAVORITES_ORGANIZE, _T("&Organize Favorites..."));
  2828. int nLastGroupStart = pSub->GetMenuItemCount();
  2829. UINT id = ID_FAVORITES_FILE_START;
  2830. CList<CString> sl;
  2831. AfxGetAppSettings().GetFav(FAV_FILE, sl);
  2832. POSITION pos = sl.GetHeadPosition();
  2833. while(pos)
  2834. {
  2835. UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
  2836. CString str = sl.GetNext(pos);
  2837. str.Replace(_T("&"), _T("&&"));
  2838. str.Replace(_T("t"), _T(" "));
  2839. CList<CString> sl;
  2840. Explode(str, sl, ';', 2);
  2841. str = sl.RemoveHead();
  2842. if(!sl.IsEmpty())
  2843. {
  2844. REFERENCE_TIME rt = 0;
  2845. if(1 == _stscanf(sl.GetHead(), _T("%I64d"), &rt) && rt > 0)
  2846. {
  2847. DVD_HMSF_TIMECODE hmsf = RT2HMSF(rt, 0);
  2848. str.Format(_T("%st[%02d:%02d:%02d]"), CString(str), hmsf.bHours, hmsf.bMinutes, hmsf.bSeconds);
  2849. }
  2850. }
  2851. if(!str.IsEmpty()) 
  2852. pSub->AppendMenu(flags, id, str);
  2853. id++;
  2854. }
  2855. if(id > ID_FAVORITES_FILE_START)
  2856. pSub->InsertMenu(nLastGroupStart, MF_SEPARATOR|MF_ENABLED|MF_BYPOSITION);
  2857. nLastGroupStart = pSub->GetMenuItemCount();
  2858. id = ID_FAVORITES_DVD_START;
  2859. AfxGetAppSettings().GetFav(FAV_DVD, sl);
  2860. pos = sl.GetHeadPosition();
  2861. while(pos)
  2862. {
  2863. UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
  2864. CString str = sl.GetNext(pos);
  2865. str.Replace(_T("&"), _T("&&"));
  2866. CList<CString> sl;
  2867. Explode(str, sl, ';', 2);
  2868. str = sl.RemoveHead();
  2869. if(!sl.IsEmpty())
  2870. {
  2871. // TODO
  2872. }
  2873. if(!str.IsEmpty()) 
  2874. pSub->AppendMenu(flags, id, str);
  2875. id++;
  2876. }
  2877. if(id > ID_FAVORITES_DVD_START)
  2878. pSub->InsertMenu(nLastGroupStart, MF_SEPARATOR|MF_ENABLED|MF_BYPOSITION);
  2879. nLastGroupStart = pSub->GetMenuItemCount();
  2880. id = ID_FAVORITES_DEVICE_START;
  2881. AfxGetAppSettings().GetFav(FAV_DEVICE, sl);
  2882. pos = sl.GetHeadPosition();
  2883. while(pos)
  2884. {
  2885. UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
  2886. CString str = sl.GetNext(pos);
  2887. str.Replace(_T("&"), _T("&&"));
  2888. CList<CString> sl;
  2889. Explode(str, sl, ';', 2);
  2890. str = sl.RemoveHead();
  2891. if(!str.IsEmpty()) 
  2892. pSub->AppendMenu(flags, id, str);
  2893. id++;
  2894. }
  2895. }
  2896. void CMainFrame::SetupShadersSubMenu()
  2897. {
  2898. CMenu* pSub = &m_shaders;
  2899. if(!IsMenu(pSub->m_hMenu)) pSub->CreatePopupMenu();
  2900. else while(pSub->RemoveMenu(0, MF_BYPOSITION));
  2901. CWinApp* pApp = AfxGetApp();
  2902. pSub->AppendMenu(MF_BYCOMMAND|MF_STRING|MF_ENABLED, ID_SHADERS_START, ResStr(IDS_SHADER_EDIT));
  2903. UINT id = ID_SHADERS_START+1;
  2904. for(int i = 0; ; i++)
  2905. {
  2906. CString str;
  2907. str.Format(_T("%d"), i);
  2908. str = pApp->GetProfileString(_T("Shaders"), str);
  2909. CList<CString> sl;
  2910. CString label = Explode(str, sl, '|');
  2911. if(label.IsEmpty()) break;
  2912. UINT flags = MF_BYCOMMAND|MF_STRING|MF_ENABLED;
  2913. if(i == 0)
  2914. {
  2915. pSub->AppendMenu(MF_SEPARATOR);
  2916. pSub->AppendMenu(flags, id++, ResStr(IDS_SHADER_OFF));
  2917. }
  2918. label.Replace(_T("&"), _T("&&"));
  2919. pSub->AppendMenu(flags, id++, label);
  2920. }
  2921. }
  2922. /////////////
  2923. void CMainFrame::ShowControls(int nCS, bool fSave)
  2924. {
  2925. int nCSprev = AfxGetAppSettings().nCS;
  2926. int hbefore = 0, hafter = 0;
  2927. m_pLastBar = NULL;
  2928. POSITION pos = m_bars.GetHeadPosition();
  2929. for(int i = 1; pos; i <<= 1)
  2930. {
  2931. CControlBar* pNext = m_bars.GetNext(pos);
  2932. ShowControlBar(pNext, !!(nCS&i), TRUE);
  2933. if(nCS&i) m_pLastBar = pNext;
  2934. CSize s = pNext->CalcFixedLayout(FALSE, TRUE);
  2935. if(nCSprev&i) hbefore += s.cy;
  2936. if(nCS&i) hafter += s.cy;
  2937. }
  2938. WINDOWPLACEMENT wp;
  2939. wp.length = sizeof(wp);
  2940. GetWindowPlacement(&wp);
  2941. if(wp.showCmd != SW_SHOWMAXIMIZED && !m_fFullScreen)
  2942. {
  2943. CRect r;
  2944. GetWindowRect(r);
  2945. MoveWindow(r.left, r.top, r.Width(), r.Height()+(hafter-hbefore));
  2946. }
  2947.     if(fSave)
  2948. AfxGetAppSettings().nCS = nCS;
  2949. RecalcLayout();
  2950. }
  2951. void CMainFrame::SetAlwaysOnTop(int i)
  2952. {
  2953. AfxGetAppSettings().iOnTop = i;
  2954. if(!m_fFullScreen)
  2955. {
  2956. const CWnd* pInsertAfter = NULL;
  2957. if(i == 0)
  2958. pInsertAfter = &wndNoTopMost;
  2959. else if(i == 1)
  2960. pInsertAfter = &wndTopMost;
  2961. else // if(i == 2)
  2962. pInsertAfter = GetMediaState() == State_Running ? &wndTopMost : &wndNoTopMost;
  2963. SetWindowPos(pInsertAfter, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
  2964. }
  2965. else if(!(GetWindowLong(m_hWnd, GWL_EXSTYLE)&WS_EX_TOPMOST))
  2966. {
  2967. SetWindowPos(&wndTopMost, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
  2968. }
  2969. }
  2970. void CMainFrame::AddTextPassThruFilter()
  2971. {
  2972. BeginEnumFilters(pGB, pEF, pBF)
  2973. {
  2974. if(!IsSplitter(pBF)) continue;
  2975. BeginEnumPins(pBF, pEP, pPin)
  2976. {
  2977. CComPtr<IPin> pPinTo;
  2978. AM_MEDIA_TYPE mt;
  2979. if(FAILED(pPin->ConnectedTo(&pPinTo)) || !pPinTo 
  2980. || FAILED(pPin->ConnectionMediaType(&mt)) 
  2981. || mt.majortype != MEDIATYPE_Text && mt.majortype != MEDIATYPE_Subtitle)
  2982. continue;
  2983. CComQIPtr<IBaseFilter> pTPTF = new CTextPassThruFilter(this);
  2984. CStringW name;
  2985. name.Format(L"TextPassThru%08x", pTPTF);
  2986. if(FAILED(pGB->AddFilter(pTPTF, name)))
  2987. continue;
  2988. HRESULT hr;
  2989. hr = pPinTo->Disconnect();
  2990. hr = pPin->Disconnect();
  2991. if(FAILED(hr = pGB->ConnectDirect(pPin, GetFirstPin(pTPTF, PINDIR_INPUT), NULL))
  2992. || FAILED(hr = pGB->ConnectDirect(GetFirstPin(pTPTF, PINDIR_OUTPUT), pPinTo, NULL)))
  2993. hr = pGB->ConnectDirect(pPin, pPinTo, NULL);
  2994. else
  2995. m_pSubStreams.AddTail(CComQIPtr<ISubStream>(pTPTF));
  2996. }
  2997. EndEnumPins
  2998. }
  2999. EndEnumFilters
  3000. }
  3001. bool CMainFrame::LoadSubtitle(CString fn)
  3002. {
  3003. CComPtr<ISubStream> pSubStream;
  3004. // TMP: maybe this will catch something for those who get a runtime error dialog when opening subtitles from cds
  3005. try
  3006. {
  3007. if(!pSubStream)
  3008. {
  3009. CAutoPtr<CVobSubFile> pVSF(new CVobSubFile(&m_csSubLock));
  3010. if(pVSF && pVSF->Open(fn) && pVSF->GetStreamCount() > 0)
  3011. pSubStream = pVSF.Detach();
  3012. }
  3013. if(!pSubStream)
  3014. {
  3015. CAutoPtr<CRenderedTextSubtitle> pRTS(new CRenderedTextSubtitle(&m_csSubLock));
  3016. if(pRTS && pRTS->Open(fn, DEFAULT_CHARSET) && pRTS->GetStreamCount() > 0)
  3017. pSubStream = pRTS.Detach();
  3018. }
  3019. }
  3020. catch(CException* e)
  3021. {
  3022. e->Delete();
  3023. }
  3024. if(pSubStream)
  3025. {
  3026. m_pSubStreams.AddTail(pSubStream);
  3027. }
  3028. return(!!pSubStream);
  3029. }
  3030. void CMainFrame::UpdateSubtitle(bool fApplyDefStyle)
  3031. {
  3032. if(!m_pCAP) return;
  3033. int i = m_iSubtitleSel;
  3034. POSITION pos = m_pSubStreams.GetHeadPosition();
  3035. while(pos && i >= 0)
  3036. {
  3037. CComPtr<ISubStream> pSubStream = m_pSubStreams.GetNext(pos);
  3038. if(i < pSubStream->GetStreamCount()) 
  3039. {
  3040. CAutoLock cAutoLock(&m_csSubLock);
  3041. pSubStream->SetStream(i);
  3042. SetSubtitle(pSubStream, fApplyDefStyle);
  3043. return;
  3044. }
  3045. i -= pSubStream->GetStreamCount();
  3046. }
  3047. m_pCAP->SetSubPicProvider(NULL);
  3048. }
  3049. void CMainFrame::SetSubtitle(ISubStream* pSubStream, bool fApplyDefStyle)
  3050. {
  3051. AppSettings& s = AfxGetAppSettings();
  3052. if(pSubStream)
  3053. {
  3054. CLSID clsid;
  3055. pSubStream->GetClassID(&clsid);
  3056. if(clsid == __uuidof(CVobSubFile))
  3057. {
  3058. CVobSubFile* pVSF = (CVobSubFile*)(ISubStream*)pSubStream;
  3059. if(fApplyDefStyle)
  3060. {
  3061. pVSF->SetAlignment(s.fOverridePlacement, s.nHorPos, s.nVerPos, 1, 1);
  3062. }
  3063. }
  3064. if(clsid == __uuidof(CVobSubStream))
  3065. {
  3066. CVobSubStream* pVSS = (CVobSubStream*)(ISubStream*)pSubStream;
  3067. if(fApplyDefStyle)
  3068. {
  3069. pVSS->SetAlignment(s.fOverridePlacement, s.nHorPos, s.nVerPos, 1, 1);
  3070. }
  3071. }
  3072. else if(clsid == __uuidof(CRenderedTextSubtitle))
  3073. {
  3074. CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)pSubStream;
  3075. STSStyle style;
  3076. if(fApplyDefStyle || pRTS->m_fUsingAutoGeneratedDefaultStyle)
  3077. {
  3078. style = s.subdefstyle;
  3079. if(s.fOverridePlacement)
  3080. {
  3081. style.scrAlignment = 2;
  3082. int w = pRTS->m_dstScreenSize.cx;
  3083. int h = pRTS->m_dstScreenSize.cy;
  3084. int mw = w - style.marginRect.left - style.marginRect.right;
  3085. style.marginRect.bottom = h - MulDiv(h, s.nVerPos, 100);
  3086. style.marginRect.left = MulDiv(w, s.nHorPos, 100) - mw/2;
  3087. style.marginRect.right = w - (style.marginRect.left + mw);
  3088. }
  3089. pRTS->SetDefaultStyle(style);
  3090. }
  3091. if(pRTS->GetDefaultStyle(style) && style.relativeTo == 2)
  3092. {
  3093. style.relativeTo = s.subdefstyle.relativeTo;
  3094. pRTS->SetDefaultStyle(style);
  3095. }
  3096. pRTS->Deinit();
  3097. }
  3098. }
  3099. if(!fApplyDefStyle)
  3100. {
  3101. m_iSubtitleSel = -1;
  3102. if(pSubStream)
  3103. {
  3104. int i = 0;
  3105. POSITION pos = m_pSubStreams.GetHeadPosition();
  3106. while(pos)
  3107. {
  3108. CComPtr<ISubStream> pSubStream2 = m_pSubStreams.GetNext(pos);
  3109. if(pSubStream == pSubStream2)
  3110. {
  3111. m_iSubtitleSel = i + pSubStream2->GetStream();
  3112. break;
  3113. }
  3114. i += pSubStream2->GetStreamCount();
  3115. }
  3116. }
  3117. }
  3118. m_nSubtitleId = (DWORD_PTR)pSubStream;
  3119. if(m_pCAP)
  3120. {
  3121. m_pCAP->SetSubPicProvider(CComQIPtr<ISubPicProvider>(pSubStream));
  3122. m_wndSubresyncBar.SetSubtitle(pSubStream, m_pCAP->GetFPS());
  3123. }
  3124. }
  3125. void CMainFrame::ReplaceSubtitle(ISubStream* pSubStreamOld, ISubStream* pSubStreamNew)
  3126. {
  3127. POSITION pos = m_pSubStreams.GetHeadPosition();
  3128. while(pos) 
  3129. {
  3130. POSITION cur = pos;
  3131. if(pSubStreamOld == m_pSubStreams.GetNext(pos))
  3132. {
  3133. m_pSubStreams.SetAt(cur, pSubStreamNew);
  3134. UpdateSubtitle();
  3135. break;
  3136. }
  3137. }
  3138. }
  3139. void CMainFrame::InvalidateSubtitle(DWORD_PTR nSubtitleId, REFERENCE_TIME rtInvalidate)
  3140. {
  3141. if(m_pCAP)
  3142. {
  3143. if(nSubtitleId == -1 || nSubtitleId == m_nSubtitleId)
  3144. m_pCAP->Invalidate(rtInvalidate);
  3145. }
  3146. }
  3147. void CMainFrame::ReloadSubtitle()
  3148. {
  3149. POSITION pos = m_pSubStreams.GetHeadPosition();
  3150. while(pos) m_pSubStreams.GetNext(pos)->Reload();
  3151. UpdateSubtitle();
  3152. }
  3153. REFERENCE_TIME CMainFrame::GetPos()
  3154. {
  3155. return(m_iMediaLoadState == MLS_LOADED ? m_wndSeekBar.GetPos() : 0);
  3156. }
  3157. REFERENCE_TIME CMainFrame::GetDur()
  3158. {
  3159. __int64 start, stop;
  3160. m_wndSeekBar.GetRange(start, stop);
  3161. return(m_iMediaLoadState == MLS_LOADED ? stop : 0);
  3162. }
  3163. void CMainFrame::SeekTo(REFERENCE_TIME rtPos, bool fSeekToKeyFrame)
  3164. {
  3165. OAFilterState fs = GetMediaState();
  3166. if(rtPos < 0) rtPos = 0;
  3167. if(m_iPlaybackMode == PM_FILE)
  3168. {
  3169. if(fs == State_Stopped)
  3170. SendMessage(WM_COMMAND, ID_PLAY_PAUSE);
  3171. HRESULT hr;
  3172. if(fSeekToKeyFrame)
  3173. {
  3174. if(!m_kfs.IsEmpty())
  3175. {
  3176. int i = rangebsearch(rtPos, m_kfs);
  3177. if(i >= 0 && i < m_kfs.GetCount())
  3178. rtPos = m_kfs[i];
  3179. }
  3180. }
  3181. hr = pMS->SetPositions(&rtPos, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning);
  3182. }
  3183. else if(m_iPlaybackMode == PM_DVD && m_iDVDDomain == DVD_DOMAIN_Title)
  3184. {
  3185. if(fs != State_Running)
  3186. SendMessage(WM_COMMAND, ID_PLAY_PLAY);
  3187. DVD_HMSF_TIMECODE tc = RT2HMSF(rtPos);
  3188. pDVDC->PlayAtTime(&tc, DVD_CMD_FLAG_Block|DVD_CMD_FLAG_Flush, NULL);
  3189. // if(fs != State_Running)
  3190. // SendMessage(WM_COMMAND, ID_PLAY_PAUSE);
  3191. }
  3192. else if(m_iPlaybackMode == PM_CAPTURE)
  3193. {
  3194. TRACE(_T("Warning (CMainFrame::SeekTo): Trying to seek in capture mode"));
  3195. }
  3196. }
  3197. void CMainFrame::CleanGraph()
  3198. {
  3199. if(!pGB) return;
  3200. BeginEnumFilters(pGB, pEF, pBF)
  3201. {
  3202. CComQIPtr<IAMFilterMiscFlags> pAMMF(pBF);
  3203. if(pAMMF && (pAMMF->GetMiscFlags()&AM_FILTER_MISC_FLAGS_IS_SOURCE))
  3204. continue;
  3205. // some capture filters forget to set AM_FILTER_MISC_FLAGS_IS_SOURCE 
  3206. // or to implement the IAMFilterMiscFlags interface
  3207. if(pBF == pVidCap || pBF == pAudCap) 
  3208. continue;
  3209. if(CComQIPtr<IFileSourceFilter>(pBF))
  3210. continue;
  3211. int nIn, nOut, nInC, nOutC;
  3212. if(CountPins(pBF, nIn, nOut, nInC, nOutC) > 0 && (nInC+nOutC) == 0)
  3213. {
  3214. TRACE(CStringW(L"Removing: ") + GetFilterName(pBF) + 'n');
  3215. pGB->RemoveFilter(pBF);
  3216. pEF->Reset();
  3217. }
  3218. }
  3219. EndEnumFilters
  3220. }
  3221. #define AUDIOBUFFERLEN 500
  3222. static void SetLatency(IBaseFilter* pBF, int cbBuffer)
  3223. {
  3224. BeginEnumPins(pBF, pEP, pPin)
  3225. {
  3226. if(CComQIPtr<IAMBufferNegotiation> pAMBN = pPin)
  3227. {
  3228. ALLOCATOR_PROPERTIES ap;
  3229. ap.cbAlign = -1;  // -1 means no preference.
  3230. ap.cbBuffer = cbBuffer;
  3231. ap.cbPrefix = -1;
  3232. ap.cBuffers = -1;
  3233. pAMBN->SuggestAllocatorProperties(&ap);
  3234. }
  3235. }
  3236. EndEnumPins
  3237. }
  3238. HRESULT CMainFrame::BuildCapture(IPin* pPin, IBaseFilter* pBF[3], const GUID& majortype, AM_MEDIA_TYPE* pmt)
  3239. {
  3240. IBaseFilter* pBuff = pBF[0];
  3241. IBaseFilter* pEnc = pBF[1];
  3242. IBaseFilter* pMux = pBF[2];
  3243. if(!pPin || !pMux) return E_FAIL;
  3244. CString err;
  3245. HRESULT hr = S_OK;
  3246. AddFilterToGraph(pGB, pMux, L"Multiplexer");
  3247. IUnknown* pPrev = pPin;
  3248. CStringW prefix, prefixl;
  3249. if(majortype == MEDIATYPE_Video) prefix = L"Video ";
  3250. else if(majortype == MEDIATYPE_Audio) prefix = L"Audio ";
  3251. prefixl = prefix;
  3252. prefixl.MakeLower();
  3253. if(pBuff)
  3254. {
  3255. hr = pGB->AddFilter(pBuff, prefix + L"Buffer");
  3256. if(FAILED(hr))
  3257. {
  3258. err = _T("Can't add ") + CString(prefixl) + _T("buffer filter");
  3259. AfxMessageBox(err);
  3260. return hr;
  3261. }
  3262. hr = pCGB->RenderStream(NULL, &majortype, pPrev, NULL, pBuff);
  3263. if(FAILED(hr))
  3264. {
  3265. err = _T("Error connecting the ") + CString(prefixl) + _T("buffer filter");
  3266. AfxMessageBox(err);
  3267. return(hr);
  3268. }
  3269. pPrev = pBuff;
  3270. }
  3271. if(pEnc)
  3272. {
  3273. hr = pGB->AddFilter(pEnc, prefix + L"Encoder");
  3274. if(FAILED(hr))
  3275. {
  3276. err = _T("Can't add ") + CString(prefixl) + _T("encoder filter");
  3277. AfxMessageBox(err);
  3278. return hr;
  3279. }
  3280. hr = pCGB->RenderStream(NULL, &majortype, pPrev, NULL, pEnc);
  3281. if(FAILED(hr))
  3282. {
  3283. err = _T("Error connecting the ") + CString(prefixl) + _T("encoder filter");
  3284. AfxMessageBox(err);
  3285. return(hr);
  3286. }
  3287. pPrev = pEnc;
  3288. if(CComQIPtr<IAMStreamConfig> pAMSC = GetFirstPin(pEnc, PINDIR_OUTPUT))
  3289. {
  3290. if(pmt->majortype == majortype)
  3291. {
  3292. hr = pAMSC->SetFormat(pmt);
  3293. if(FAILED(hr))
  3294. {
  3295. err = _T("Can't set compression format on the ") + CString(prefixl) + _T("encoder filter");
  3296. AfxMessageBox(err);
  3297. return(hr);
  3298. }
  3299. }
  3300. }
  3301. }
  3302. // if(pMux)
  3303. {
  3304. hr = pCGB->RenderStream(NULL, &majortype, pPrev, NULL, pMux);
  3305. if(FAILED(hr))
  3306. {
  3307. err = _T("Error connecting ") + CString(prefixl) + _T(" to the muliplexer filter");
  3308. AfxMessageBox(err);
  3309. return(hr);
  3310. }
  3311. }
  3312. CleanGraph();
  3313. return S_OK;
  3314. }
  3315. bool CMainFrame::BuildToCapturePreviewPin(
  3316. IBaseFilter* pVidCap, IPin** ppVidCapPin, IPin** ppVidPrevPin, 
  3317. IBaseFilter* pAudCap, IPin** ppAudCapPin, IPin** ppAudPrevPin)
  3318. {
  3319. HRESULT hr;
  3320. *ppVidCapPin = *ppVidPrevPin = NULL; 
  3321. *ppAudCapPin = *ppAudPrevPin = NULL;
  3322. CComPtr<IPin> pDVAudPin;
  3323. if(pVidCap)
  3324. {
  3325. CComPtr<IPin> pPin;
  3326. if(!pAudCap // only look for interleaved stream when we don't use any other audio capture source
  3327. && SUCCEEDED(pCGB->FindPin(pVidCap, PINDIR_OUTPUT, &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Interleaved, TRUE, 0, &pPin)))
  3328. {
  3329. CComPtr<IBaseFilter> pDVSplitter;
  3330. hr = pDVSplitter.CoCreateInstance(CLSID_DVSplitter);
  3331. hr = pGB->AddFilter(pDVSplitter, L"DV Splitter");
  3332. hr = pCGB->RenderStream(NULL, &MEDIATYPE_Interleaved, pPin, NULL, pDVSplitter);
  3333. pPin = NULL;
  3334. hr = pCGB->FindPin(pDVSplitter, PINDIR_OUTPUT, NULL, &MEDIATYPE_Video, TRUE, 0, &pPin);
  3335. hr = pCGB->FindPin(pDVSplitter, PINDIR_OUTPUT, NULL, &MEDIATYPE_Audio, TRUE, 0, &pDVAudPin);
  3336. CComPtr<IBaseFilter> pDVDec;
  3337. hr = pDVDec.CoCreateInstance(CLSID_DVVideoCodec);
  3338. hr = pGB->AddFilter(pDVDec, L"DV Video Decoder");
  3339. hr = pCGB->RenderStream(NULL, &MEDIATYPE_Video, pPin, NULL, pDVDec);
  3340. pPin = NULL;
  3341. hr = pCGB->FindPin(pDVDec, PINDIR_OUTPUT, NULL, &MEDIATYPE_Video, TRUE, 0, &pPin);
  3342. }
  3343. else if(SUCCEEDED(pCGB->FindPin(pVidCap, PINDIR_OUTPUT, &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, TRUE, 0, &pPin)))
  3344. {
  3345. }
  3346. else
  3347. {
  3348. AfxMessageBox(_T("No video capture pin found"));
  3349. return(false);
  3350. }
  3351. CComPtr<IBaseFilter> pSmartTee;
  3352. hr = pSmartTee.CoCreateInstance(CLSID_SmartTee);
  3353. hr = pGB->AddFilter(pSmartTee, L"Smart Tee (video)");
  3354. hr = pCGB->RenderStream(NULL, &MEDIATYPE_Video, pPin, NULL, pSmartTee);
  3355. hr = pSmartTee->FindPin(L"Preview", ppVidPrevPin);
  3356. hr = pSmartTee->FindPin(L"Capture", ppVidCapPin);
  3357. }
  3358. if(pAudCap || pDVAudPin)
  3359. {
  3360. CComPtr<IPin> pPin;
  3361. if(pDVAudPin)
  3362. {
  3363. pPin = pDVAudPin;
  3364. }
  3365. else if(SUCCEEDED(pCGB->FindPin(pAudCap, PINDIR_OUTPUT, &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, TRUE, 0, &pPin)))
  3366. {
  3367. }
  3368. else
  3369. {
  3370. AfxMessageBox(_T("No audio capture pin found"));
  3371. return(false);
  3372. }
  3373. CComPtr<IBaseFilter> pSmartTee;
  3374. hr = pSmartTee.CoCreateInstance(CLSID_SmartTee);
  3375. hr = pGB->AddFilter(pSmartTee, L"Smart Tee (audio)");
  3376. hr = pCGB->RenderStream(NULL, &MEDIATYPE_Audio, pPin, NULL, pSmartTee);
  3377. hr = pSmartTee->FindPin(L"Preview", ppAudPrevPin);
  3378. hr = pSmartTee->FindPin(L"Capture", ppAudCapPin);
  3379. }
  3380. return(true);
  3381. }
  3382. bool CMainFrame::BuildGraphVideoAudio(bool fVPreview, bool fVCapture, bool fAPreview, bool fACapture)
  3383. {
  3384. if(!pCGB) return(false);
  3385. SaveMediaState;
  3386. HRESULT hr;
  3387. NukeDownstream(pVidCap, pGB);
  3388. NukeDownstream(pAudCap, pGB);
  3389. CleanGraph();
  3390. if(pAMVSCCap) hr = pAMVSCCap->SetFormat(&m_wndCaptureBar.m_capdlg.m_mtv);
  3391. if(pAMVSCPrev) hr = pAMVSCPrev->SetFormat(&m_wndCaptureBar.m_capdlg.m_mtv);
  3392. if(pAMASC) hr = pAMASC->SetFormat(&m_wndCaptureBar.m_capdlg.m_mta);
  3393. CComPtr<IBaseFilter> pVidBuffer = m_wndCaptureBar.m_capdlg.m_pVidBuffer;
  3394. CComPtr<IBaseFilter> pAudBuffer = m_wndCaptureBar.m_capdlg.m_pAudBuffer;
  3395. CComPtr<IBaseFilter> pVidEnc = m_wndCaptureBar.m_capdlg.m_pVidEnc;
  3396. CComPtr<IBaseFilter> pAudEnc = m_wndCaptureBar.m_capdlg.m_pAudEnc;
  3397. CComPtr<IBaseFilter> pMux = m_wndCaptureBar.m_capdlg.m_pMux;
  3398. CComPtr<IBaseFilter> pDst = m_wndCaptureBar.m_capdlg.m_pDst;
  3399. CComPtr<IBaseFilter> pAudMux = m_wndCaptureBar.m_capdlg.m_pAudMux;
  3400. CComPtr<IBaseFilter> pAudDst = m_wndCaptureBar.m_capdlg.m_pAudDst;
  3401. bool fFileOutput = (pMux && pDst) || (pAudMux && pAudDst);
  3402. bool fCapture = (fVCapture || fACapture);
  3403. if(pAudCap)
  3404. {
  3405. AM_MEDIA_TYPE* pmt = &m_wndCaptureBar.m_capdlg.m_mta;
  3406. int ms = (fACapture && fFileOutput && m_wndCaptureBar.m_capdlg.m_fAudOutput) ? AUDIOBUFFERLEN : 60;
  3407. if(pMux != pAudMux && fACapture) SetLatency(pAudCap, -1);
  3408. else if(pmt->pbFormat) SetLatency(pAudCap, ((WAVEFORMATEX*)pmt->pbFormat)->nAvgBytesPerSec * ms / 1000);
  3409. }
  3410. CComPtr<IPin> pVidCapPin, pVidPrevPin, pAudCapPin, pAudPrevPin;
  3411. BuildToCapturePreviewPin(pVidCap, &pVidCapPin, &pVidPrevPin, pAudCap, &pAudCapPin, &pAudPrevPin);
  3412. CGraphBuilderCapture gb(pGB, m_wndView.m_hWnd);
  3413. // if(pVidCap)
  3414. {
  3415. bool fVidPrev = pVidPrevPin && fVPreview;
  3416. bool fVidCap = pVidCapPin && fVCapture && fFileOutput && m_wndCaptureBar.m_capdlg.m_fVidOutput;
  3417. if(fVidPrev && !fVidCap && pVidCapPin)
  3418. {
  3419. pVidPrevPin = pVidCapPin;
  3420. pVidCapPin = NULL;
  3421. }
  3422. if(fVidPrev)
  3423. {
  3424. m_pCAP = NULL;
  3425. gb.Render(pVidPrevPin);
  3426. gb.FindInterface(__uuidof(ISubPicAllocatorPresenter), (void**)&m_pCAP);
  3427. }
  3428. if(fVidCap)
  3429. {
  3430. IBaseFilter* pBF[3] = {pVidBuffer, pVidEnc, pMux};
  3431. HRESULT hr = BuildCapture(pVidCapPin, pBF, MEDIATYPE_Video, &m_wndCaptureBar.m_capdlg.m_mtcv);
  3432. }
  3433. pAMDF = NULL;
  3434. pCGB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pVidCap, IID_IAMDroppedFrames, (void**)&pAMDF);
  3435. }
  3436. // if(pAudCap)
  3437. {
  3438. bool fAudPrev = pAudPrevPin && fAPreview;
  3439. bool fAudCap = pAudCapPin && fACapture && fFileOutput && m_wndCaptureBar.m_capdlg.m_fAudOutput;
  3440. if(fAudPrev)
  3441. {
  3442. gb.Render(fAudCap ? pAudPrevPin : pAudCapPin);
  3443. }
  3444. if(fAudCap)
  3445. {
  3446. IBaseFilter* pBF[3] = {pAudBuffer, pAudEnc, pAudMux ? pAudMux : pMux};
  3447. HRESULT hr = BuildCapture(pAudCapPin, pBF, MEDIATYPE_Audio, &m_wndCaptureBar.m_capdlg.m_mtca);
  3448. }
  3449. }
  3450. if((pVidCap || pAudCap) && fCapture && fFileOutput)
  3451. {
  3452. if(pMux != pDst)
  3453. {
  3454. hr = pGB->AddFilter(pDst, L"File Writer V/A");
  3455. hr = pCGB->RenderStream(NULL, NULL, pMux, NULL, pDst);
  3456. }
  3457. if(CComQIPtr<IConfigAviMux> pCAM = pMux)
  3458. {
  3459. int nIn, nOut, nInC, nOutC;
  3460. CountPins(pMux, nIn, nOut, nInC, nOutC);
  3461. pCAM->SetMasterStream(nInC-1);
  3462. // pCAM->SetMasterStream(-1);
  3463. pCAM->SetOutputCompatibilityIndex(FALSE);
  3464. }
  3465. if(CComQIPtr<IConfigInterleaving> pCI = pMux)
  3466. {
  3467. // if(FAILED(pCI->put_Mode(INTERLEAVE_CAPTURE)))
  3468. if(FAILED(pCI->put_Mode(INTERLEAVE_NONE_BUFFERED)))
  3469. pCI->put_Mode(INTERLEAVE_NONE);
  3470. REFERENCE_TIME rtInterleave = 10000i64*AUDIOBUFFERLEN, rtPreroll = 0;//10000i64*500
  3471. pCI->put_Interleaving(&rtInterleave, &rtPreroll);
  3472. }
  3473. if(pMux != pAudMux && pAudMux != pAudDst)
  3474. {
  3475. hr = pGB->AddFilter(pAudDst, L"File Writer A");
  3476. hr = pCGB->RenderStream(NULL, NULL, pAudMux, NULL, pAudDst);
  3477. }
  3478. }
  3479. REFERENCE_TIME stop = MAX_TIME;
  3480. hr = pCGB->ControlStream(&PIN_CATEGORY_CAPTURE, NULL, NULL, NULL, &stop, 0, 0); // stop in the infinite
  3481. CleanGraph();
  3482. OpenSetupVideo();
  3483. OpenSetupStatsBar();
  3484. OpenSetupStatusBar();
  3485. RestoreMediaState;
  3486. return(true);
  3487. }
  3488. bool CMainFrame::StartCapture()
  3489. {
  3490. if(!pCGB || m_fCapturing) return(false);
  3491. if(!m_wndCaptureBar.m_capdlg.m_pMux && !m_wndCaptureBar.m_capdlg.m_pDst) return(false);
  3492. HRESULT hr;
  3493. ::SetPriorityClass(::GetCurrentProcess(), HIGH_PRIORITY_CLASS);
  3494. // rare to see two capture filters to support IAMPushSource at the same time...
  3495. // hr = CComQIPtr<IAMGraphStreams>(pGB)->SyncUsingStreamOffset(TRUE); // TODO:
  3496. BuildGraphVideoAudio(
  3497. !!m_wndCaptureBar.m_capdlg.m_fVidPreview, true, 
  3498. !!m_wndCaptureBar.m_capdlg.m_fAudPreview, true);
  3499. hr = pME->CancelDefaultHandling(EC_REPAINT);
  3500. SendMessage(WM_COMMAND, ID_PLAY_PLAY);
  3501. m_fCapturing = true;
  3502. return(true);
  3503. }
  3504. bool CMainFrame::StopCapture()
  3505. {
  3506. if(!pCGB || !m_fCapturing) return(false);
  3507. if(!m_wndCaptureBar.m_capdlg.m_pMux && !m_wndCaptureBar.m_capdlg.m_pDst) return(false);
  3508. HRESULT hr;
  3509. m_wndStatusBar.SetStatusMessage(_T("Completing..."));
  3510. m_fCapturing = false;
  3511. BuildGraphVideoAudio(
  3512. !!m_wndCaptureBar.m_capdlg.m_fVidPreview, false, 
  3513. !!m_wndCaptureBar.m_capdlg.m_fAudPreview, false);
  3514. hr = pME->RestoreDefaultHandling(EC_REPAINT);
  3515. ::SetPriorityClass(::GetCurrentProcess(), AfxGetAppSettings().priority);
  3516. m_rtDurationOverride = -1;
  3517. return(true);
  3518. }
  3519. //
  3520. void CMainFrame::ShowOptions(int idPage)
  3521. {
  3522. AppSettings& s = AfxGetAppSettings();
  3523. CPPageSheet options(ResStr(IDS_OPTIONS_CAPTION), pGB, this, idPage);
  3524. if(options.DoModal() == IDOK)
  3525. {
  3526. if(!m_fFullScreen)
  3527. SetAlwaysOnTop(s.iOnTop);
  3528. m_wndView.LoadLogo();
  3529. s.UpdateData(true);
  3530. }
  3531. }
  3532. void CMainFrame::StartWebServer(int nPort)
  3533. {
  3534. if(!m_pWebServer)
  3535. m_pWebServer.Attach(new CWebServer(this, nPort));
  3536. }
  3537. void CMainFrame::StopWebServer()
  3538. {
  3539. if(m_pWebServer)
  3540. m_pWebServer.Free();
  3541. }
  3542. CString CMainFrame::GetStatusMessage()
  3543. {
  3544. CString str;
  3545. m_wndStatusBar.m_status.GetWindowText(str);
  3546. return str;
  3547. }
  3548. void CMainFrame::SendStatusMessage(CString msg, int nTimeOut)
  3549. {
  3550. KillTimer(TIMER_STATUSERASER);
  3551. m_playingmsg.Empty();
  3552. if(nTimeOut <= 0) return;
  3553. m_playingmsg = msg;
  3554. SetTimer(TIMER_STATUSERASER, nTimeOut, NULL);
  3555. }
  3556. void CMainFrame::OpenCurPlaylistItem(REFERENCE_TIME rtStart)
  3557. {
  3558. if(m_wndPlaylistBar.GetCount() == 0)
  3559. return;
  3560. CPlaylistItem pli;
  3561. if(!m_wndPlaylistBar.GetCur(pli)) m_wndPlaylistBar.SetFirst();
  3562. if(!m_wndPlaylistBar.GetCur(pli)) return;
  3563. CAutoPtr<OpenMediaData> p(m_wndPlaylistBar.GetCurOMD(rtStart));
  3564. if(p) OpenMedia(p);
  3565. }
  3566. void CMainFrame::AddCurDevToPlaylist()
  3567. {
  3568. if(m_iPlaybackMode == PM_CAPTURE)
  3569. {
  3570. m_wndPlaylistBar.Append(
  3571. m_VidDispName, 
  3572. m_AudDispName, 
  3573. m_wndCaptureBar.m_capdlg.GetVideoInput(), 
  3574. m_wndCaptureBar.m_capdlg.GetVideoChannel(), 
  3575. m_wndCaptureBar.m_capdlg.GetAudioInput()
  3576. );
  3577. }
  3578. }
  3579. static int s_fOpenedThruThread = false;
  3580. void CMainFrame::OpenMedia(CAutoPtr<OpenMediaData> pOMD)
  3581. {
  3582. // shortcut
  3583. if(OpenDeviceData* p = dynamic_cast<OpenDeviceData*>(pOMD.m_p))
  3584. {
  3585. if(m_iMediaLoadState == MLS_LOADED && pAMTuner
  3586. && m_VidDispName == p->DisplayName[0] && m_AudDispName == p->DisplayName[1])
  3587. {
  3588. m_wndCaptureBar.m_capdlg.SetVideoInput(p->vinput);
  3589. m_wndCaptureBar.m_capdlg.SetVideoChannel(p->vchannel);
  3590. m_wndCaptureBar.m_capdlg.SetAudioInput(p->ainput);
  3591. SendNowPlayingToMSN();
  3592. return;
  3593. }
  3594. }
  3595. if(m_iMediaLoadState != MLS_CLOSED)
  3596. CloseMedia();
  3597. AppSettings& s = AfxGetAppSettings();
  3598. bool fUseThread = true;
  3599. if(OpenFileData* p = dynamic_cast<OpenFileData*>(pOMD.m_p))
  3600. {
  3601. if(p->fns.GetCount() > 0)
  3602. {
  3603. engine_t e = s.Formats.GetEngine(p->fns.GetHead());
  3604. fUseThread = e == DirectShow /*|| e == RealMedia || e == QuickTime*/;
  3605. }
  3606. }
  3607. else if(OpenDeviceData* p = dynamic_cast<OpenDeviceData*>(pOMD.m_p))
  3608. {
  3609. fUseThread = false;
  3610. }
  3611. if(m_pGraphThread && fUseThread
  3612. && AfxGetAppSettings().fEnableWorkerThreadForOpening)
  3613. {
  3614. m_pGraphThread->PostThreadMessage(CGraphThread::TM_OPEN, 0, (LPARAM)pOMD.Detach());
  3615. s_fOpenedThruThread = true;
  3616. }
  3617. else
  3618. {
  3619. OpenMediaPrivate(pOMD);
  3620. s_fOpenedThruThread = false;
  3621. }
  3622. }
  3623. void CMainFrame::CloseMedia()
  3624. {
  3625. if(m_iMediaLoadState == MLS_CLOSING)
  3626. {
  3627. TRACE(_T("WARNING: CMainFrame::CloseMedia() called twice or moren"));
  3628. return;
  3629. }
  3630. int nTimeWaited = 0;
  3631. while(m_iMediaLoadState == MLS_LOADING)
  3632. {
  3633. m_fOpeningAborted = true;
  3634. if(pGB) pGB->Abort(); // TODO: lock on graph objects somehow, this is not thread safe
  3635. if(nTimeWaited > 5*1000 && m_pGraphThread)
  3636. {
  3637. MessageBeep(MB_ICONEXCLAMATION);
  3638. TRACE(_T("CRITICAL ERROR: !!! Must kill opener thread !!!"));
  3639. TerminateThread(m_pGraphThread->m_hThread, -1);
  3640. m_pGraphThread = (CGraphThread*)AfxBeginThread(RUNTIME_CLASS(CGraphThread));
  3641. s_fOpenedThruThread = false;
  3642. break;
  3643. }
  3644. Sleep(50);
  3645. nTimeWaited += 50;
  3646. }
  3647. m_fOpeningAborted = false;
  3648. m_closingmsg.Empty();
  3649. m_iMediaLoadState = MLS_CLOSING;
  3650. OnFilePostClosemedia();
  3651. if(m_pGraphThread && s_fOpenedThruThread)
  3652. {
  3653. CAMEvent e;
  3654. m_pGraphThread->PostThreadMessage(CGraphThread::TM_CLOSE, 0, (LPARAM)&e);
  3655. e.Wait(); // either opening or closing has to be blocked to prevent reentering them, closing is the better choice
  3656. }
  3657. else
  3658. {
  3659. CloseMediaPrivate();
  3660. }
  3661. UnloadExternalObjects();
  3662. }
  3663. //
  3664. // CGraphThread
  3665. //
  3666. IMPLEMENT_DYNCREATE(CGraphThread, CWinThread)
  3667. BOOL CGraphThread::InitInstance()
  3668. {
  3669. AfxSocketInit();
  3670. return SUCCEEDED(CoInitialize(0)) ? TRUE : FALSE;
  3671. }
  3672. int CGraphThread::ExitInstance()
  3673. {
  3674. CoUninitialize();
  3675. return __super::ExitInstance();
  3676. }
  3677. BEGIN_MESSAGE_MAP(CGraphThread, CWinThread)
  3678. ON_THREAD_MESSAGE(TM_EXIT, OnExit)
  3679. ON_THREAD_MESSAGE(TM_OPEN, OnOpen)
  3680. ON_THREAD_MESSAGE(TM_CLOSE, OnClose)
  3681. END_MESSAGE_MAP()
  3682. void CGraphThread::OnExit(WPARAM wParam, LPARAM lParam)
  3683. {
  3684. PostQuitMessage(0);
  3685. if(CAMEvent* e = (CAMEvent*)lParam) e->Set();
  3686. }
  3687. void CGraphThread::OnOpen(WPARAM wParam, LPARAM lParam)
  3688. {
  3689. if(m_pMainFrame)
  3690. {
  3691. CAutoPtr<OpenMediaData> pOMD((OpenMediaData*)lParam);
  3692. m_pMainFrame->OpenMediaPrivate(pOMD);
  3693. }
  3694. }
  3695. void CGraphThread::OnClose(WPARAM wParam, LPARAM lParam)
  3696. {
  3697. if(m_pMainFrame) m_pMainFrame->CloseMediaPrivate();
  3698. if(CAMEvent* e = (CAMEvent*)lParam) e->Set();
  3699. }