=====================================================

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 RTLedm_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}// 各种Barm_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 defaultPOSITION pos = m_dockingbars.GetHeadPosition();while (pos) {m_dockingbars.GetNext(pos)->ShowWindow(SW_HIDE);}m_fileDropTarget.Register(this);const CAppSettings& s = AfxGetAppSettings();// Load the controlsm_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_LITEm_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 playif ((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 minutem_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 subtitlem_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 playbackULONG ulAvailable, ulCurrent;// LocationCString 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' thechapter start time if this happens */if (m_lChapterStartTime > tsec) {m_lChapterStartTime = tsec;}}}m_wndInfoBar.SetLine(ResStr(IDS_INFOBAR_LOCATION), Location);// VideoCString 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);// AudioCString 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);// SubtitlesCString 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 playbackSetThreadExecutionState(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);
}

Media Player Classic - HC 源代码分析 4:核心类 (CMainFrame)(3)相关推荐

  1. Media Player Classic - HC 源代码分析 3:核心类 (CMainFrame)(2)

    ===================================================== Media Player Classic - HC 源代码分析系列文章列表: Media P ...

  2. Media Player Classic - HC 源代码分析 2:核心类 (CMainFrame)(1)

    ===================================================== Media Player Classic - HC 源代码分析系列文章列表: Media P ...

  3. Media Player Classic - HC 源代码分析 7:详细信息选项卡(CPPageFileInfoDetails)

    ===================================================== Media Player Classic - HC 源代码分析系列文章列表: Media P ...

  4. Media Player Classic - HC 源代码分析 6:MediaInfo选项卡 (CPPageFileMediaInfo)

    ===================================================== Media Player Classic - HC 源代码分析系列文章列表: Media P ...

  5. Media Player Classic - HC 源代码分析 5:关于对话框 (CAboutDlg)

    ===================================================== Media Player Classic - HC 源代码分析系列文章列表: Media P ...

  6. Media Player Classic - HC 源代码分析 1:整体结构

    ===================================================== Media Player Classic - HC 源代码分析系列文章列表: Media P ...

  7. Media Player Classic - HC 源代码分析 8:RenderFile函数详细分析(CFGManager)

    前面有两篇文章分析了Media Player Classic - HC(mpc-hc)的源代码中的核心类 CMainFrame: Media Player Classic - HC 源代码分析 2:核 ...

  8. Media Player Classic - HC 源代码分析 9:CFGManager类详细分析(CFGManager)

    上一篇文章分析了Media Player Classic - HC(mpc-hc)的源代码中的CFGManager类的RenderFile函数: Media Player Classic - HC 源 ...

  9. Media Player Classic - HC 源代码分析 14:PIN连接过程中推模式和拉模式区别

    前面有两篇文章讲解了PIN连接过程中需要做2件事情: 媒体类型的协商 分配器的协商 推模式和拉模式关于媒体类型的协商调用的接口都一样,主要的区别还是在分配器的协商. 前面讲解的分配器的协商过程是推模式 ...

最新文章

  1. 程序语言python循环_Python语言程序设计之一--for循环
  2. [python调试笔记] 编译运行h5py
  3. java.net.ServerSocket 解析
  4. ELK:kibana使用的lucene查询语法
  5. prometheus python client
  6. Mac IDEA启动SpringBoot项目过慢
  7. python一次性输入多个数_python如何利用input函数输入多个参数?
  8. listen函数的第二个参数_signal(SIGPIPE,?SIG_IGN)listen函数中backlog参数分析
  9. Svn服务器之必须提交更改日志篇
  10. 9月我的第一次,新的感悟
  11. C#之向文件追加内容
  12. Lena——计算机视觉中的女神被人忽视的部分
  13. fw150rm刷openwrt固件_迅捷FW150R刷TP741N后再刷Openwrt和DDWRT以及固件还原
  14. 洛谷题单-【算法1-5】贪心
  15. 从微博数据看国产手机格局 新四大取代中华酷联
  16. 计算机二级office应用与设计,全国计算机等级考试二级教程——MS Office高级应用与设计(2021年版)...
  17. uploadify的简单使用
  18. qq登录界面句柄_注册QQ飞车日服账号
  19. [RK3288][Android6.0] Skia中的编解码小结
  20. C语言开发单片机为什么大多数都采用全局变量的形式?

热门文章

  1. 书籍推荐:《Secrets of the Oracle Database》
  2. UVA11752 The Super Powers【超级幂+暴力+数论】
  3. Ubuntu下BOINC服务器安装(step8失败)
  4. 弦论 —— 宇宙的琴弦
  5. matlab 基础 —— 输出相关信息(pause、fprintf)
  6. 进程间通信 IPC、LPC、RPC
  7. hive 操作(二)——使用 mysql 作为 hive 的metastore
  8. lisp 任意点 曲线距离_lisp程序能求多段线上任意一点到其中一个端点的距离,,每次要量桩号很烦...哪位大侠给个..谢谢了...........
  9. python工资这么高为什么不学-小白入行年薪21万,为什么Python岗位薪资越来越高?...
  10. python画50个图-python绘制多个子图的实例