=====================================================
Media Player Classic - HC 源代码分析系列文章列表:
Media Player Classic - HC 源代码分析 1:整体结构
Media Player Classic - HC 源代码分析 2:核心类 (CMainFrame)(1)
Media Player Classic - HC 源代码分析 3:核心类 (CMainFrame)(2)
Media Player Classic - HC 源代码分析 4:核心类 (CMainFrame)(3)
Media Player Classic - HC 源代码分析 5:关于对话框 (CAboutDlg)
Media Player Classic - HC 源代码分析 6:MediaInfo选项卡 (CPPageFileMediaInfo)
Media Player Classic - HC 源代码分析 7:详细信息选项卡(CPPageFileInfoDetails)
=====================================================
此前已经写了2篇文章介绍Media Player Classic - HC (mpc-hc)源代码中的核心类 CMainFrame:
Media Player Classic - HC 源代码分析 2:核心类 (CMainFrame)(1)
Media Player Classic - HC 源代码分析 3:核心类 (CMainFrame)(2)
此前的文章一直都是围绕着OpenMedia()以及其调用的函数进行分析的。研究的都是和文件打开有关系的功能。在这里再介绍一些其它函数。
在mpc-hc开始运行的时候,会调用OnCreate():
<span style="font-family:Arial;font-size:12px;">//刚打开的时候加载 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (__super::OnCreate(lpCreateStruct) == -1) { return -1; } //加载菜单 m_popup.LoadMenu(IDR_POPUP); m_popupmain.LoadMenu(IDR_POPUPMAIN); // create a view to occupy the client area of the frame // 创建视频画面部分? if (!m_wndView.Create(nullptr, nullptr, AFX_WS_DEFAULT_VIEW, CRect(0, 0, 0, 0), this, AFX_IDW_PANE_FIRST, nullptr)) { TRACE(_T("Failed to create view window\n")); return -1; } // Should never be RTLed m_wndView.ModifyStyleEx(WS_EX_LAYOUTRTL, WS_EX_NOINHERITLAYOUT); // static bars //各种状态栏 BOOL bResult = m_wndStatusBar.Create(this); if (bResult) { bResult = m_wndStatsBar.Create(this); } if (bResult) { bResult = m_wndInfoBar.Create(this); } if (bResult) { bResult = m_wndToolBar.Create(this); } if (bResult) { bResult = m_wndSeekBar.Create(this); } if (!bResult) { TRACE(_T("Failed to create all control bars\n")); return -1; // fail to create } // 各种Bar m_pFullscreenWnd = DEBUG_NEW CFullscreenWnd(this); m_bars.AddTail(&m_wndSeekBar); m_bars.AddTail(&m_wndToolBar); m_bars.AddTail(&m_wndInfoBar); m_bars.AddTail(&m_wndStatsBar); m_bars.AddTail(&m_wndStatusBar); m_wndSeekBar.Enable(false); // dockable bars // 可停靠的 EnableDocking(CBRS_ALIGN_ANY); m_dockingbars.RemoveAll(); m_wndSubresyncBar.Create(this, AFX_IDW_DOCKBAR_TOP, &m_csSubLock); m_wndSubresyncBar.SetBarStyle(m_wndSubresyncBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC); m_wndSubresyncBar.EnableDocking(CBRS_ALIGN_ANY); m_wndSubresyncBar.SetHeight(200); m_dockingbars.AddTail(&m_wndSubresyncBar); m_wndPlaylistBar.Create(this, AFX_IDW_DOCKBAR_BOTTOM); m_wndPlaylistBar.SetBarStyle(m_wndPlaylistBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC); m_wndPlaylistBar.EnableDocking(CBRS_ALIGN_ANY); m_wndPlaylistBar.SetHeight(100); m_dockingbars.AddTail(&m_wndPlaylistBar); m_wndPlaylistBar.LoadPlaylist(GetRecentFile()); m_wndEditListEditor.Create(this, AFX_IDW_DOCKBAR_RIGHT); m_wndEditListEditor.SetBarStyle(m_wndEditListEditor.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC); m_wndEditListEditor.EnableDocking(CBRS_ALIGN_ANY); m_dockingbars.AddTail(&m_wndEditListEditor); m_wndEditListEditor.SetHeight(100); m_wndCaptureBar.Create(this, AFX_IDW_DOCKBAR_LEFT); m_wndCaptureBar.SetBarStyle(m_wndCaptureBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC); m_wndCaptureBar.EnableDocking(CBRS_ALIGN_LEFT | CBRS_ALIGN_RIGHT); m_dockingbars.AddTail(&m_wndCaptureBar); m_wndNavigationBar.Create(this, AFX_IDW_DOCKBAR_LEFT); m_wndNavigationBar.SetBarStyle(m_wndNavigationBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC); m_wndNavigationBar.EnableDocking(CBRS_ALIGN_LEFT | CBRS_ALIGN_RIGHT); m_dockingbars.AddTail(&m_wndNavigationBar); m_wndShaderEditorBar.Create(this, AFX_IDW_DOCKBAR_TOP); m_wndShaderEditorBar.SetBarStyle(m_wndShaderEditorBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC); m_wndShaderEditorBar.EnableDocking(CBRS_ALIGN_ANY); m_dockingbars.AddTail(&m_wndShaderEditorBar); // Hide all dockable bars by default POSITION pos = m_dockingbars.GetHeadPosition(); while (pos) { m_dockingbars.GetNext(pos)->ShowWindow(SW_HIDE); } m_fileDropTarget.Register(this); const CAppSettings& s = AfxGetAppSettings(); // Load the controls m_nCS = s.nCS; ShowControls(m_nCS); //是否在最前? SetAlwaysOnTop(s.iOnTop); //显示系统托盘图标 ShowTrayIcon(s.fTrayIcon); //焦点 SetFocus(); //创建CGraphThread类的线程 m_pGraphThread = (CGraphThread*)AfxBeginThread(RUNTIME_CLASS(CGraphThread)); //设置。。 if (m_pGraphThread) { m_pGraphThread->SetMainFrame(this); } if (s.nCmdlnWebServerPort != 0) { if (s.nCmdlnWebServerPort > 0) { StartWebServer(s.nCmdlnWebServerPort); } else if (s.fEnableWebServer) { StartWebServer(s.nWebServerPort); } } // Casimir666 : reload Shaders { CString strList = s.strShaderList; CString strRes; int curPos = 0; strRes = strList.Tokenize(_T("|"), curPos); while (!strRes.IsEmpty()) { m_shaderlabels.AddTail(strRes); strRes = strList.Tokenize(_T("|"), curPos); } } { CString strList = s.strShaderListScreenSpace; CString strRes; int curPos = 0; strRes = strList.Tokenize(_T("|"), curPos); while (!strRes.IsEmpty()) { m_shaderlabelsScreenSpace.AddTail(strRes); strRes = strList.Tokenize(_T("|"), curPos); } } m_bToggleShader = s.fToggleShader; m_bToggleShaderScreenSpace = s.fToggleShaderScreenSpace; //标题 m_strTitle.LoadString(IDR_MAINFRAME); #ifdef MPCHC_LITE m_strTitle += _T(" Lite"); #endif //设置窗口标题 SetWindowText(m_strTitle); m_Lcd.SetMediaTitle(LPCTSTR(m_strTitle)); WTSRegisterSessionNotification(); if (s.bNotifySkype) { m_pSkypeMoodMsgHandler.Attach(DEBUG_NEW SkypeMoodMsgHandler()); m_pSkypeMoodMsgHandler->Connect(m_hWnd); } return 0; }</span>
在mpc-hc关闭的时候,会调用OnDestroy():
<span style="font-family:Arial;font-size:12px;">//关闭的时候加载 void CMainFrame::OnDestroy() { WTSUnRegisterSessionNotification(); //关闭系统托盘图标 ShowTrayIcon(false); m_fileDropTarget.Revoke(); //线程还在运行的话 if (m_pGraphThread) { CAMMsgEvent e; //退出 m_pGraphThread->PostThreadMessage(CGraphThread::TM_EXIT, 0, (LPARAM)&e); if (!e.Wait(5000)) { TRACE(_T("ERROR: Must call TerminateThread() on CMainFrame::m_pGraphThread->m_hThread\n")); TerminateThread(m_pGraphThread->m_hThread, (DWORD) - 1); } } if (m_pFullscreenWnd) { if (m_pFullscreenWnd->IsWindow()) { m_pFullscreenWnd->DestroyWindow(); } delete m_pFullscreenWnd; } __super::OnDestroy(); }</span>
在关闭一个媒体的时候,会调用OnClose():
//关闭的时候加载 void CMainFrame::OnClose() { //获取设置 CAppSettings& s = AfxGetAppSettings(); // Casimir666 : save shaders list { POSITION pos; CString strList = ""; pos = m_shaderlabels.GetHeadPosition(); while (pos) { strList += m_shaderlabels.GetAt(pos) + "|"; m_dockingbars.GetNext(pos); } s.strShaderList = strList; } { POSITION pos; CString strList = ""; pos = m_shaderlabelsScreenSpace.GetHeadPosition(); while (pos) { strList += m_shaderlabelsScreenSpace.GetAt(pos) + "|"; m_dockingbars.GetNext(pos); } s.strShaderListScreenSpace = strList; } s.fToggleShader = m_bToggleShader; s.fToggleShaderScreenSpace = m_bToggleShaderScreenSpace; s.dZoomX = m_ZoomX; s.dZoomY = m_ZoomY; //存储播放列表 m_wndPlaylistBar.SavePlaylist(); //存储控制条 SaveControlBars(); ShowWindow(SW_HIDE); //关闭媒体(非private) CloseMedia(); s.WinLircClient.DisConnect(); s.UIceClient.DisConnect(); SendAPICommand(CMD_DISCONNECT, L"\0"); // according to CMD_NOTIFYENDOFSTREAM (ctrl+f it here), you're not supposed to send NULL here //调用父类onclose __super::OnClose(); }
同时还有一个定时器函数OnTimer()。根据不同的nIDEvent做不同的处理操作。
//定时刷新的操作 void CMainFrame::OnTimer(UINT_PTR nIDEvent) { switch (nIDEvent) { //当前播放到的位置 case TIMER_STREAMPOSPOLLER: if (m_iMediaLoadState == MLS_LOADED) { REFERENCE_TIME rtNow = 0, rtDur = 0; //播放方式是文件的时候(还可以是DVD或者摄像头) if (GetPlaybackMode() == PM_FILE) { //当前位置 m_pMS->GetCurrentPosition(&rtNow); //时常 m_pMS->GetDuration(&rtDur); // Casimir666 : autosave subtitle sync after play if ((m_nCurSubtitle >= 0) && (m_rtCurSubPos != rtNow)) { if (m_lSubtitleShift != 0) { if (m_wndSubresyncBar.SaveToDisk()) { m_OSD.DisplayMessage(OSD_TOPLEFT, ResStr(IDS_AG_SUBTITLES_SAVED), 500); } else { m_OSD.DisplayMessage(OSD_TOPLEFT, ResStr(IDS_MAINFRM_4)); } } m_nCurSubtitle = -1; m_lSubtitleShift = 0; } if (!m_fEndOfStream) { CAppSettings& s = AfxGetAppSettings(); if (m_bRememberFilePos) { FILE_POSITION* filePosition = s.filePositions.GetLatestEntry(); if (filePosition) { filePosition->llPosition = rtNow; LARGE_INTEGER time; QueryPerformanceCounter(&time); LARGE_INTEGER freq; QueryPerformanceFrequency(&freq); if ((time.QuadPart - m_liLastSaveTime.QuadPart) >= 30 * freq.QuadPart) { // save every half of minute m_liLastSaveTime = time; s.filePositions.SaveLatestEntry(); } } } } if (m_rtDurationOverride >= 0) { rtDur = m_rtDurationOverride; } //设置滑动条控件的参数(位置等。。。) g_bNoDuration = rtDur <= 0; m_wndSeekBar.Enable(rtDur > 0); m_wndSeekBar.SetRange(0, rtDur); m_wndSeekBar.SetPos(rtNow); m_OSD.SetRange(0, rtDur); m_OSD.SetPos(rtNow); m_Lcd.SetMediaRange(0, rtDur); m_Lcd.SetMediaPos(rtNow); } else if (GetPlaybackMode() == PM_CAPTURE) { //如果是摄像头的话,就没有时长信息了 m_pMS->GetCurrentPosition(&rtNow); if (m_fCapturing && m_wndCaptureBar.m_capdlg.m_pMux) { CComQIPtr<IMediaSeeking> pMuxMS = m_wndCaptureBar.m_capdlg.m_pMux; if (!pMuxMS || FAILED(pMuxMS->GetCurrentPosition(&rtNow))) { rtNow = 0; } } if (m_rtDurationOverride >= 0) { rtDur = m_rtDurationOverride; } g_bNoDuration = rtDur <= 0; m_wndSeekBar.Enable(false); m_wndSeekBar.SetRange(0, rtDur); m_wndSeekBar.SetPos(rtNow); m_OSD.SetRange(0, rtDur); m_OSD.SetPos(rtNow); m_Lcd.SetMediaRange(0, rtDur); m_Lcd.SetMediaPos(rtNow); } if (m_pCAP && GetPlaybackMode() != PM_FILE) { g_bExternalSubtitleTime = true; if (m_pDVDI) { DVD_PLAYBACK_LOCATION2 Location; if (m_pDVDI->GetCurrentLocation(&Location) == S_OK) { double fps = Location.TimeCodeFlags == DVD_TC_FLAG_25fps ? 25.0 : Location.TimeCodeFlags == DVD_TC_FLAG_30fps ? 30.0 : Location.TimeCodeFlags == DVD_TC_FLAG_DropFrame ? 29.97 : 25.0; REFERENCE_TIME rtTimeCode = HMSF2RT(Location.TimeCode, fps); m_pCAP->SetTime(rtTimeCode); } else { m_pCAP->SetTime(/*rtNow*/m_wndSeekBar.GetPos()); } } else { // Set rtNow to support DVB subtitle m_pCAP->SetTime(rtNow); } } else { g_bExternalSubtitleTime = false; } } break; case TIMER_STREAMPOSPOLLER2: if (m_iMediaLoadState == MLS_LOADED) { __int64 start, stop, pos; m_wndSeekBar.GetRange(start, stop); pos = m_wndSeekBar.GetPosReal(); GUID tf; m_pMS->GetTimeFormat(&tf); if (GetPlaybackMode() == PM_CAPTURE && !m_fCapturing) { CString str = ResStr(IDS_CAPTURE_LIVE); long lChannel = 0, lVivSub = 0, lAudSub = 0; if (m_pAMTuner && m_wndCaptureBar.m_capdlg.IsTunerActive() && SUCCEEDED(m_pAMTuner->get_Channel(&lChannel, &lVivSub, &lAudSub))) { CString ch; ch.Format(_T(" (ch%d)"), lChannel); str += ch; } m_wndStatusBar.SetStatusTimer(str); } else { m_wndStatusBar.SetStatusTimer(pos, stop, !!m_wndSubresyncBar.IsWindowVisible(), &tf); if (m_bRemainingTime) { m_OSD.DisplayMessage(OSD_TOPLEFT, m_wndStatusBar.GetStatusTimer()); } } m_wndSubresyncBar.SetTime(pos); if (m_pCAP && GetMediaState() == State_Paused) { m_pCAP->Paint(false); } } break; case TIMER_FULLSCREENCONTROLBARHIDER: { CPoint p; GetCursorPos(&p); CRect r; GetWindowRect(r); bool fCursorOutside = !r.PtInRect(p); CWnd* pWnd = WindowFromPoint(p); if (pWnd && (m_wndView == *pWnd || m_wndView.IsChild(pWnd) || fCursorOutside)) { if (AfxGetAppSettings().nShowBarsWhenFullScreenTimeOut >= 0) { ShowControls(CS_NONE); } } } break; case TIMER_FULLSCREENMOUSEHIDER: { CPoint p; GetCursorPos(&p); CRect r; GetWindowRect(r); bool fCursorOutside = !r.PtInRect(p); CWnd* pWnd = WindowFromPoint(p); if (IsD3DFullScreenMode()) { if (pWnd && !m_bInOptions && *pWnd == *m_pFullscreenWnd) { m_pFullscreenWnd->ShowCursor(false); } KillTimer(TIMER_FULLSCREENMOUSEHIDER); } else { if (pWnd && !m_bInOptions && (m_wndView == *pWnd || m_wndView.IsChild(pWnd) || fCursorOutside)) { m_fHideCursor = true; SetCursor(nullptr); } } } break; //统计量 case TIMER_STATS: { //接收端质量信息:抖动,抖动,视音频同步情况等。。。 if (m_pQP) { CString rate; rate.Format(_T("%.2f"), m_dSpeedRate); rate = _T("(") + rate + _T("x)"); //信息 CString info; int val = 0; //平均帧率 m_pQP->get_AvgFrameRate(&val); // We hang here due to a lock that never gets released. info.Format(_T("%d.%02d %s"), val / 100, val % 100, rate); m_wndStatsBar.SetLine(ResStr(IDS_AG_FRAMERATE), info); int avg, dev; //抖动 m_pQP->get_AvgSyncOffset(&avg); m_pQP->get_DevSyncOffset(&dev); info.Format(ResStr(IDS_STATSBAR_SYNC_OFFSET_FORMAT), avg, dev); m_wndStatsBar.SetLine(ResStr(IDS_STATSBAR_SYNC_OFFSET), info); //掉帧 int drawn, dropped; m_pQP->get_FramesDrawn(&drawn); m_pQP->get_FramesDroppedInRenderer(&dropped); info.Format(IDS_MAINFRM_6, drawn, dropped); m_wndStatsBar.SetLine(ResStr(IDS_AG_FRAMES), info); //抖动 m_pQP->get_Jitter(&val); info.Format(_T("%d ms"), val); m_wndStatsBar.SetLine(ResStr(IDS_STATSBAR_JITTER), info); } //缓存信息 if (m_pBI) { CAtlList<CString> sl; //获取数量 for (int i = 0, j = m_pBI->GetCount(); i < j; i++) { int samples, size; //获取缓存状态 if (S_OK == m_pBI->GetStatus(i, samples, size)) { CString str; str.Format(_T("[%d]: %03d/%d KB"), i, samples, size / 1024); sl.AddTail(str); } } if (!sl.IsEmpty()) { CString str; str.Format(_T("%s (p%u)"), Implode(sl, ' '), m_pBI->GetPriority()); m_wndStatsBar.SetLine(ResStr(IDS_AG_BUFFERS), str); } } //比特率信息 CInterfaceList<IBitRateInfo> pBRIs; BeginEnumFilters(m_pGB, pEF, pBF) { BeginEnumPins(pBF, pEP, pPin) { if (CComQIPtr<IBitRateInfo> pBRI = pPin) { pBRIs.AddTail(pBRI); } } EndEnumPins; if (!pBRIs.IsEmpty()) { CAtlList<CString> sl; POSITION pos = pBRIs.GetHeadPosition(); for (int i = 0; pos; i++) { //比特率接口 IBitRateInfo* pBRI = pBRIs.GetNext(pos); //当前比特率 DWORD cur = pBRI->GetCurrentBitRate() / 1000; //平均比特率 DWORD avg = pBRI->GetAverageBitRate() / 1000; if (avg == 0) { continue; } //添加到字符串 CString str; if (cur != avg) { str.Format(_T("[%d]: %u/%u Kb/s"), i, avg, cur); } else { str.Format(_T("[%d]: %u Kb/s"), i, avg); } //加入 sl.AddTail(str); } if (!sl.IsEmpty()) { m_wndStatsBar.SetLine(ResStr(IDS_STATSBAR_BITRATE), Implode(sl, ' ') + ResStr(IDS_STATSBAR_BITRATE_AVG_CUR)); } break; } } EndEnumFilters; if (GetPlaybackMode() == PM_DVD) { // we also use this timer to update the info panel for DVD playback ULONG ulAvailable, ulCurrent; // Location CString Location('-'); DVD_PLAYBACK_LOCATION2 loc; ULONG ulNumOfVolumes, ulVolume; DVD_DISC_SIDE Side; ULONG ulNumOfTitles; ULONG ulNumOfChapters; if (SUCCEEDED(m_pDVDI->GetCurrentLocation(&loc)) && SUCCEEDED(m_pDVDI->GetNumberOfChapters(loc.TitleNum, &ulNumOfChapters)) && SUCCEEDED(m_pDVDI->GetDVDVolumeInfo(&ulNumOfVolumes, &ulVolume, &Side, &ulNumOfTitles))) { Location.Format(IDS_MAINFRM_9, ulVolume, ulNumOfVolumes, loc.TitleNum, ulNumOfTitles, loc.ChapterNum, ulNumOfChapters); ULONG tsec = (loc.TimeCode.bHours * 3600) + (loc.TimeCode.bMinutes * 60) + (loc.TimeCode.bSeconds); /* This might not always work, such as on resume */ if (loc.ChapterNum != m_lCurrentChapter) { m_lCurrentChapter = loc.ChapterNum; m_lChapterStartTime = tsec; } else { /* If a resume point was used, and the user chapter jumps, then it might do some funky time jumping. Try to 'fix' the chapter start time if this happens */ if (m_lChapterStartTime > tsec) { m_lChapterStartTime = tsec; } } } m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_LOCATION), Location); // Video CString Video('-'); DVD_VideoAttributes VATR; if (SUCCEEDED(m_pDVDI->GetCurrentAngle(&ulAvailable, &ulCurrent)) && SUCCEEDED(m_pDVDI->GetCurrentVideoAttributes(&VATR))) { Video.Format(IDS_MAINFRM_10, ulCurrent, ulAvailable, VATR.ulSourceResolutionX, VATR.ulSourceResolutionY, VATR.ulFrameRate, VATR.ulAspectX, VATR.ulAspectY); } m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_VIDEO), Video); // Audio CString Audio('-'); DVD_AudioAttributes AATR; if (SUCCEEDED(m_pDVDI->GetCurrentAudio(&ulAvailable, &ulCurrent)) && SUCCEEDED(m_pDVDI->GetAudioAttributes(ulCurrent, &AATR))) { CString lang; if (AATR.Language) { int len = GetLocaleInfo(AATR.Language, LOCALE_SENGLANGUAGE, lang.GetBuffer(64), 64); lang.ReleaseBufferSetLength(max(len - 1, 0)); } else { lang.Format(IDS_AG_UNKNOWN, ulCurrent + 1); } switch (AATR.LanguageExtension) { case DVD_AUD_EXT_NotSpecified: default: break; case DVD_AUD_EXT_Captions: lang += _T(" (Captions)"); break; case DVD_AUD_EXT_VisuallyImpaired: lang += _T(" (Visually Impaired)"); break; case DVD_AUD_EXT_DirectorComments1: lang += _T(" (Director Comments 1)"); break; case DVD_AUD_EXT_DirectorComments2: lang += _T(" (Director Comments 2)"); break; } CString format = GetDVDAudioFormatName(AATR); Audio.Format(IDS_MAINFRM_11, lang, format, AATR.dwFrequency, AATR.bQuantization, AATR.bNumberOfChannels, (AATR.bNumberOfChannels > 1 ? ResStr(IDS_MAINFRM_13) : ResStr(IDS_MAINFRM_12))); m_wndStatusBar.SetStatusBitmap( AATR.bNumberOfChannels == 1 ? IDB_AUDIOTYPE_MONO : AATR.bNumberOfChannels >= 2 ? IDB_AUDIOTYPE_STEREO : IDB_AUDIOTYPE_NOAUDIO); } m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_AUDIO), Audio); // Subtitles CString Subtitles('-'); BOOL bIsDisabled; DVD_SubpictureAttributes SATR; if (SUCCEEDED(m_pDVDI->GetCurrentSubpicture(&ulAvailable, &ulCurrent, &bIsDisabled)) && SUCCEEDED(m_pDVDI->GetSubpictureAttributes(ulCurrent, &SATR))) { CString lang; int len = GetLocaleInfo(SATR.Language, LOCALE_SENGLANGUAGE, lang.GetBuffer(64), 64); lang.ReleaseBufferSetLength(max(len - 1, 0)); switch (SATR.LanguageExtension) { case DVD_SP_EXT_NotSpecified: default: break; case DVD_SP_EXT_Caption_Normal: lang += _T(""); break; case DVD_SP_EXT_Caption_Big: lang += _T(" (Big)"); break; case DVD_SP_EXT_Caption_Children: lang += _T(" (Children)"); break; case DVD_SP_EXT_CC_Normal: lang += _T(" (CC)"); break; case DVD_SP_EXT_CC_Big: lang += _T(" (CC Big)"); break; case DVD_SP_EXT_CC_Children: lang += _T(" (CC Children)"); break; case DVD_SP_EXT_Forced: lang += _T(" (Forced)"); break; case DVD_SP_EXT_DirectorComments_Normal: lang += _T(" (Director Comments)"); break; case DVD_SP_EXT_DirectorComments_Big: lang += _T(" (Director Comments, Big)"); break; case DVD_SP_EXT_DirectorComments_Children: lang += _T(" (Director Comments, Children)"); break; } if (bIsDisabled) { lang = _T("-"); } Subtitles.Format(_T("%s"), lang); } m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_SUBTITLES), Subtitles); } else if (GetPlaybackMode() == PM_CAPTURE && AfxGetAppSettings().iDefaultCaptureDevice == 1) { CComQIPtr<IBDATuner> pTun = m_pGB; BOOLEAN bPresent; BOOLEAN bLocked; LONG lDbStrength; LONG lPercentQuality; CString Signal; if (SUCCEEDED(pTun->GetStats(bPresent, bLocked, lDbStrength, lPercentQuality)) && bPresent) { Signal.Format(ResStr(IDS_STATSBAR_SIGNAL_FORMAT), (int)lDbStrength, lPercentQuality); m_wndStatsBar.SetLine(ResStr(IDS_STATSBAR_SIGNAL), Signal); } } else if (GetPlaybackMode() == PM_FILE) { UpdateChapterInInfoBar(); } if (GetMediaState() == State_Running && !m_fAudioOnly) { BOOL fActive = FALSE; if (SystemParametersInfo(SPI_GETSCREENSAVEACTIVE, 0, &fActive, 0)) { SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, FALSE, nullptr, SPIF_SENDWININICHANGE); // this might not be needed at all... SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, fActive, nullptr, SPIF_SENDWININICHANGE); } fActive = FALSE; if (SystemParametersInfo(SPI_GETPOWEROFFACTIVE, 0, &fActive, 0)) { SystemParametersInfo(SPI_SETPOWEROFFACTIVE, FALSE, nullptr, SPIF_SENDWININICHANGE); // this might not be needed at all... SystemParametersInfo(SPI_SETPOWEROFFACTIVE, fActive, nullptr, SPIF_SENDWININICHANGE); } // prevent screensaver activate, monitor sleep/turn off after playback SetThreadExecutionState(ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED); } } break; case TIMER_STATUSERASER: { KillTimer(TIMER_STATUSERASER); m_playingmsg.Empty(); } break; case TIMER_DVBINFO_UPDATER: KillTimer(TIMER_DVBINFO_UPDATER); ShowCurrentChannelInfo(false, false); break; } __super::OnTimer(nIDEvent); }