MainFrm.cpp
上传用户:tangyu_668
上传日期:2014-02-27
资源大小:678k
文件大小:244k
源码类别:

多媒体编程

开发平台:

Visual C++

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