`

简单 分析splayer

 
阅读更多
CMPlayerCApp类中 包含 Settings设置类
Settings设置类中包含 CRecentFileAndURLList 近期文件和url列表类
Settings设置类中包含 CRendererSettingsEVR 渲染设置类

在CMPlayerCApp构造函数中
_set_invalid_parameter_handler 建立了一个过程invalid_arg处理程序
_CrtSetReportMode(_CRT_ASSERT, 0); 禁用断言消息框。
QueryPerformanceFrequency 查看性能频率

CMPlayerCApp::InitInstance()中

设置
DetourRestoreAfterWith()
DetourTransactionBegin()
DetourUpdateThread(GetCurrentThread())
DetourAttach 关联某函数
Detours是微软提供的一个开发库,使用它可以简单、高校、稳定地实现API HOOK的功能。
Detours是一个可以在x86、x64和IA64平台上测试任意Win32函数的程序开发库。它可以通过为目标函数重写在内存中的代码而达到拦截Win32函数的目的。Detours还可以将任意的DLL或数据片段(称之为有效载荷)注入到任意Win32二进制文件中。Detours 被广泛应用在微软内部和其他行业中。

CFilterMapper2::Init(); 关联注册表
DetourTransactionCommit() 绕道交易提交
Mine_DeviceIoControl 设备输入输出控制

OleInitialize(0) 是初始化Ole的运行环境,Ole是在Com的基础上作的扩展,是ActiveX运行的基础。


Mine_DeviceIoControl 连续两次设置

//////////////////////////////////////////////////////////////////////////
// WTL/ATL supporting logic
::CoInitialize(NULL);
::DefWindowProc(NULL, 0, 0, 0L);
WTL::AtlInitCommonControls(ICC_BAR_CLASSES);
_Module.Init(NULL, AfxGetInstanceHandle());
//////////////////////////////////////////////////////////////////////////

SetLanguage(-1) 连续创建两次文件 在Lang目录中 default

void CMPlayerCApp::PreProcessCommandLine() 分析命令行参数 添加到到m_cmdIn向量中

bool CMPlayerCApp::StoreSettingsToRegistry() 保存设置到注册表 只是判断 SVPlayer 和 Splayer

bool CMPlayerCApp::StoreSettingsToIni()保存设置到ini文件中

GetIniPath()得到ini路径 里面是通过CSVPToolBox函数获得

m_s.ParseCommandLine(m_cmdln);
CRendererSettingsEVR 成员m_s 根据m_cmdIn向量 设置m_s成员 m_cmdIn由命令行参数控制


DwmIsCompositionEnabled
获取一个值,指示是否启用桌面窗口管理器(DWM)组成。应用程序可以听的组成状态变化通过处理的WM_DWMCOMPOSITIONCHANGED的通知。

DwmEnableComposition 启用或禁用桌面窗口管理器(DWM)组成。

DwmExtendFrameIntoClientArea 延伸到客户区窗口框架。

DwmDefWindowProc 默认为桌面窗口管理器窗口程序(DWM)打在非客户区的测试。

OpenThemeData 打开一个窗口,其关联的类的主题数据。

GetThemeSysFont 检索系统字体的LOGFONT。

DrawThemeTextEx 使用由视觉样式定义的颜色和字体绘制文本。

CloseThemeData 关闭的主题数据句柄。

Direct3DCreate9Ex 创建一个IDirect3D9Ex对象并返回它的一个接口。

InitChannelMap() 初始化声道

GetAcceleratorTable() 根据以HotkeyController创建加速表

//检查文件关联
//if ( m_s.fCheckFileAsscOnStartup ){
// ChkDefPlayerControlBar dlg_chkdefplayer;
// if( ! dlg_chkdefplayer.IsDefaultPlayer() ){
// if(m_s.fPopupStartUpExtCheck || (IsVista() && !IsUserAnAdmin())){
// dlg_chkdefplayer.ShowWindow(SW_SHOWNOACTIVATE);
// }else{
// dlg_chkdefplayer.SetDefaultPlayer();
// }
// }
// // dlg_chkdefplayer.setDefaultPlayer();

BOOL CMPlayerCApp::PumpMessage() 中有判断鼠标位置的 操作导航

BOOL CMPlayerCApp::RegDelnodeRecurse (HKEY hKeyRoot, LPTSTR lpSubKey)删除注册表项及其所有子项/值。

BOOL CMPlayerCApp::RegDelnode (HKEY hKeyRoot, LPTSTR lpSubKey)删除注册表项及其所有子项/值。

CreateAcceleratorTable 该函数创建一个加速键表。


class CMainFrame :
public CFrameWnd, 窗体
public CDropTarget , 拖动文件事件
public CGraphCore
视频接口

void OpenCreateGraphObject(OpenMediaData* pOMD); 创建视频接口对象
HRESULT OpenMMSUrlStream(CString szFn);
void OpenFile(OpenFileData* pOFD);
void OpenDVD(OpenDVDData* pODD);
void OpenCapture(OpenDeviceData* pODD);
void OpenCustomizeGraph();
void OpenSetupVideo();
void OpenSetupAudio();


// shaders 着色器
CAtlList<CString> m_shaderlabels;
void SetShaders( BOOL silent = false);
void UpdateShaders(CString label);

// capturing 捕获
bool m_fCapturing;
HRESULT BuildCapture(IPin* pPin, IBaseFilter* pBF[3], const GUID& majortype, AM_MEDIA_TYPE* pmt); // pBF: 0 buff, 1 enc, 2 mux, pmt is for 1 enc
bool BuildToCapturePreviewPin(IBaseFilter* pVidCap, IPin** pVidCapPin, IPin** pVidPrevPin,
IBaseFilter* pAudCap, IPin** pAudCapPin, IPin** pAudPrevPin);
bool BuildGraphVideoAudio(int fVPreview, bool fVCapture, int fAPreview, bool fACapture);
bool DoCapture(), StartCapture(), StopCapture();

void ReRenderOrLoadMedia(BOOL bNoMoreDXVAForThisMedia = FALSE); 重新渲染或重新加载

// Snapshot 快照
bool GetDIB(BYTE** ppData, long& size, bool fSilent = false);
void SaveDIB(LPCTSTR fn, BYTE* pData, long size);
BOOL IsRendererCompatibleWithSaveImage();
void SaveImage(LPCTSTR fn = NULL);
void AutoSaveImage(LPCTSTR fn, bool istoobig = false);

void SaveThumbnails(LPCTSTR fn);

……


LRESULT CMainFrame::OnNcCalcSizeNewUI( WPARAM wParam, LPARAM lParam)可以在窗口大小或位置改变时控制客户区的内容。

void CMainFrame::RecalcLayout(BOOL bNotify) OnCreateHelper中产生
当标准工具栏或状态栏隐藏或者显示,或者窗口调整大小时,调用这个方法。

void CMainFrame::SearchSkinFolder() 在OnCreate中 产生

CreateIC 为专用设备创建一个信息场景。信息场景可用来快速获取某设备的信息而无须创建设备场景这样的系统开销。

MediaCenterController::GetInstance()->SetFrame(m_wndView.m_hWnd);媒体中心控制器

OnCmdMsg是类CCmdTarget的虚函数,用来查找和分派消息

在OnCreate里面 各种窗体创建

m_fileDropTarget.Register(this); 注册文件拖入


ShowControls( ( s.nCS | (s.bShowControlBar ? CS_COLORCONTROLBAR : 0) ) & ~CS_SEEKBAR , false );显示各控件

void CMainFrame::SetAlwaysOnTop(int i, BOOL setSetting) 设置窗口置顶

void CMainFrame::ShowTrayIcon(bool fShow) 托盘

void CMainFrame::OnSetFocus(CWnd* pOldWnd) 获得焦点 时判断是否需要设置窗口置顶

m_pGraphThread = (CGraphThread*)AfxBeginThread(RUNTIME_CLASS(CGraphThread));产生一个线程

s.RegGlobalAccelKey(this->m_hWnd); 注册快捷键

ImmAssociateContextEx 此功能改变输入法的背景和指定的窗口或子女之间的关联。

打开文件流程分析:
void CMainFrame::OnFileOpenQuick()
{
正在加载或列表未生成 则直接返回
if(m_iMediaLoadState == MLS_LOADING || !IsWindow(m_wndPlaylistBar)) return;

近期文件列表
CRecentFileList& MRU = AfxGetAppSettings().MRU;

CString szLastFile; 最后一次看的视频文件

MRU.ReadList(); 读取列表的文件路径

if(MRU.GetSize() > 0){
szLastFile = MRU[0]; 把读取的文件信息取出
}

CString filter;
CAtlArray<CString> mask;
从设置里面读取过滤的设置
AfxGetAppSettings().Formats.GetFilter(filter, mask);

COpenFileDlg fd(mask, true, NULL, szLastFile,
OFN_EXPLORER|OFN_ENABLESIZING|OFN_HIDEREADONLY|OFN_ALLOWMULTISELECT|OFN_ENABLEINCLUDENOTIFY,
filter, this);
if(fd.DoModal() != IDOK) return; 显示出打开文件对话框


CAtlList<CString> fns;


POSITION pos = fd.GetStartPosition();
while(pos) fns.AddTail(fd.GetNextPathName(pos)); 把选中的文件加入进来


bool fMultipleFiles = false;


判断是否多选 或选中的是目录
if(fns.GetCount() > 1
|| fns.GetCount() == 1
&& (fns.GetHead()[fns.GetHead().GetLength()-1] == '\\'
|| fns.GetHead()[fns.GetHead().GetLength()-1] == '*'))
{
fMultipleFiles = true;
}


猜测 关闭Media
SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);


ShowWindow(SW_SHOW);
SetForegroundWindow();


列表打开文件
m_wndPlaylistBar.Open(fns, fMultipleFiles);


播放列表个数为一 且可见 并且不是自由的 则显示或隐藏
if(m_wndPlaylistBar.GetCount() == 1 && m_wndPlaylistBar.IsWindowVisible() && !m_wndPlaylistBar.IsFloating())
{
ShowControlBar(&m_wndPlaylistBar, FALSE, TRUE);
}


OpenCurPlaylistItem(); 打开当前列表选中项
}


进入 OpenCurPlaylistItem 函数分析 参数为树节点 默认为零


void CMainFrame::OpenCurPlaylistItem(REFERENCE_TIME rtStart)
{
如果列表中没有 则直接退出
if(m_wndPlaylistBar.GetCount() == 0) return;


CPlaylistItem pli;
得到当前选中项 如果没有则选中第一项
if(!m_wndPlaylistBar.GetCur(pli)) m_wndPlaylistBar.SetFirst();
if(!m_wndPlaylistBar.GetCur(pli)) return;


AppSettings& s = AfxGetAppSettings();


if(rtStart == 0){
CString fn;
fn = pli.m_fns.GetHead(); 获得文件路径


// SVP_LogMsg5(L"GetFav Start1 %s", fn);
favtype ft ;
ft = FAV_FILE;


if (!fn.IsEmpty() && s.autoResumePlay){
文件存在 且 自动恢复播放
std::string str = Strings::WStringToString(fn.GetBuffer());
CString szMatchmd5 = HashController::GetInstance()->GetMD5Hash(str.c_str(), str.length()).c_str();


SVP_LogMsg5(L"GetFav Start %s", szMatchmd5);


CAtlList<CString> sl;
s.GetFav(ft, sl, TRUE); 得到以前保存的数据


CString PosStr ;
POSITION pos = sl.GetHeadPosition(); 获得
while(pos){ //判断以前是否播放过
PosStr = sl.GetNext(pos) ;
if( PosStr.Find(szMatchmd5 + _T(";")) == 0 ){
break;
}else{
PosStr.Empty();
}
}
if(!PosStr.IsEmpty()){ 如果未播放 则记录


int iPos = PosStr.ReverseFind( _T(';') );
if(iPos >= 0){
CString s2 = PosStr.Right( PosStr.GetLength() - iPos - 1 );
_stscanf(s2, _T("%I64d"), &rtStart); // pos
}
SVP_LogMsg5(L"Got %f", double(rtStart) );
}
是否恢复退出时的状态
m_is_resume_from_last_exit_point = TRUE;
//SVP_LogMsg5(L"GetFav Done");
}
}else if(rtStart == -1){
rtStart = 0;
}

打开媒体文件 根据OpenMediaData*初始化 OpenMediaData里面保存了路径和rtStart
CAutoPtr<OpenMediaData> p(m_wndPlaylistBar.GetCurOMD(rtStart));


if(p) OpenMedia(p); 根据CAutoPtr<OpenMediaData> 进行打开播放
}


进入OpenMedia进行 打开播放
void CMainFrame::OpenMedia(CAutoPtr<OpenMediaData> pOMD)
{
// shortcut
if(OpenDeviceData* p = dynamic_cast<OpenDeviceData*>(pOMD.m_p))
{
如果是DeviceData数据
if(m_iMediaLoadState == MLS_LOADED && pAMTuner
&& m_VidDispName == p->DisplayName[0] && m_AudDispName == p->DisplayName[1])
{
m_wndCaptureBar.m_capdlg.SetVideoInput(p->vinput);
m_wndCaptureBar.m_capdlg.SetVideoChannel(p->vchannel);
m_wndCaptureBar.m_capdlg.SetAudioInput(p->ainput);
return;
}
}


如果当前正在播放则关闭
if(m_iMediaLoadState != MLS_CLOSED)
CloseMedia();


更改状态
m_iMediaLoadState = MLS_LOADING; // HACK: hides the logo
m_wndView.Invalidate();


AppSettings& s = AfxGetAppSettings();


bool fUseThread = true;


if(OpenFileData* p = dynamic_cast<OpenFileData*>(pOMD.m_p))
{
如果是打开的文件
if(p->fns.GetCount() > 0)
{
解码类型
engine_t e = s.Formats.GetEngine(p->fns.GetHead());
如果是DirectShow 类型 只有.ram .rm .ra .qt .mov .ram 不需要
fUseThread = e == DirectShow /*|| e == RealMedia || e == QuickTime*/;


}
}
else if(OpenDeviceData* p = dynamic_cast<OpenDeviceData*>(pOMD.m_p))
{
fUseThread = false;


}


如果渲染线程存在 且 需要使用线程 且 需要打开工作线程
if(m_pGraphThread && fUseThread&&AfxGetAppSettings().fEnableWorkerThreadForOpening)
m_pGraphThread->PostThreadMessage(CGraphThread::TM_OPEN, 0, (LPARAM)pOMD.Detach());
else
OpenMediaPrivate(pOMD);


}


进入 CGraphThread::TM_OPEN 事件 用一个新的线程打开播放文件
void CGraphThread::OnOpen(WPARAM wParam, LPARAM lParam)
{
if(m_pMainFrame)
{
CAutoPtr<OpenMediaData> pOMD((OpenMediaData*)lParam);
m_pMainFrame->OpenMediaPrivate(pOMD);
}
}






进入OpenMediaPrivate 分析


bool CMainFrame::OpenMediaPrivate(CAutoPtr<OpenMediaData> pOMD)
{
CString err, aborted(_T("Aborted"));
AppSettings& s = AfxGetAppSettings(); 获得设置信息


{
打开关闭锁
CAutoLock mOpenCloseLock(&m_csOpenClose);


s.bIsIVM = false;
s.szCurrentExtension.Empty();


如果状态不是关闭 且 不是正在加载 则出错
一定要是加载状态 或是关闭状态
if(m_iMediaLoadState != MLS_CLOSED && m_iMediaLoadState != MLS_LOADING)
{
ASSERT(0);
return(false);
}


s.bExternalSubtitleTime = false;


设置Slider
m_wndSeekBar.SetRange(0, 100);


记录
s.szFGMLog.Empty();


设置声道
s.SetNumberOfSpeakers(s.iDecSpeakers , -1);


正在加载状态
m_iMediaLoadState = MLS_LOADING;


2.5秒加载
SetTimer(TIMER_LOADING, 2500, NULL);


不显示关闭
// FIXME: Don't show "Closed" initially
PostMessage(WM_KICKIDLE); 调用主线程更新的东西


m_fUpdateInfoBar = false;


try
{
打开终止 异常
if(m_fOpeningAborted) throw aborted;


if(OpenFileData* pOFD = dynamic_cast<OpenFileData*>(pOMD.m_p))
{
文件不存在异常
if(pOFD->fns.IsEmpty()) throw ResStr(IDS_MSG_THROW_FILE_NOT_FOUND);


CString fn = pOFD->fns.GetHead();


取出格式
s.szCurrentExtension = fn.Right(4).MakeLower();


格式比较
.ivm格式
if(s.szCurrentExtension == _T(".ivm"))
s.bIsIVM = true;


s.bDisableSoftCAVCForce = false;

.mkv格式
if(!(s.useGPUAcel && s.bHasCUDAforCoreAVC) && !s.bDisableSoftCAVC
&& s.szCurrentExtension == _T(".mkv"))
{
FILE* fp;
if ( _wfopen_s( &fp, fn, _T("rb")) == 0)
{
char matchbuf[0x4000];
size_t iRead = fread(matchbuf, sizeof( char ), 0x4000 ,fp);
if( iRead > 200 && find_string_in_buf(matchbuf, iRead-100, "wpredp=2") > 0 )
s.bDisableSoftCAVCForce = true;


fclose(fp);
}
}


int i = fn.Find(_T(":\\"));
if(i > 0)
{
判断文件所在盘
CString drive = fn.Left(i+2);
UINT type = GetDriveType(drive);
CAtlList<CString> sl;


可移动的 驱动
if(type == DRIVE_REMOVABLE || type == DRIVE_CDROM && GetCDROMType(drive[0], sl) != CDROM_Audio)
{
int ret = IDRETRY;
while(ret == IDRETRY)
{
WIN32_FIND_DATA findFileData;
HANDLE h = FindFirstFile(fn, &findFileData);
if(h != INVALID_HANDLE_VALUE)
{
FindClose(h);
ret = IDOK;
}
else
{
CString msg;
msg.Format(ResStr(IDS_MSG_WARN_NOT_FOUND_AND_PLS_INSERT_DISK), fn);
ret = AfxMessageBox(msg, MB_RETRYCANCEL);
}
}


if(ret != IDOK) throw aborted;
}else{
否则是本地盘 判断文件是否存在
CSVPToolBox svpTool;
if(!svpTool.ifFileExist(fn, true)){
//SVP_LogMsg5(L"SVP 文件不存在" );
throw ResStr(IDS_MSG_THROW_FILE_NOT_EXIST);
}
}
}
}


打开终止异常
if(m_fOpeningAborted) throw aborted;


创建渲染对象 关键一
OpenCreateGraphObject(pOMD); 待分析


打开终止异常
if(m_fOpeningAborted) throw aborted;


m_pCAP2 = NULL;
m_pCAP = NULL;
m_pSVPSub = NULL;


判断打开的文件的类型 待分析
if(OpenFileData* p = dynamic_cast<OpenFileData*>(pOMD.m_p)) OpenFile(p);
else if(OpenDVDData* p = dynamic_cast<OpenDVDData*>(pOMD.m_p)) OpenDVD(p);
else if(OpenDeviceData* p = dynamic_cast<OpenDeviceData*>(pOMD.m_p)) OpenCapture(p);
else throw _T("Can't open, invalid input parameters");


查找相关接口
pGB->FindInterface(__uuidof(ISubPicAllocatorPresenter), (void**)&m_pCAP, FALSE);
pGB->FindInterface(__uuidof(ISubPicAllocatorPresenterRender), (void**)&m_pCAPR, TRUE);
pGB->FindInterface(__uuidof(ISubPicAllocatorPresenter2), (void**)&m_pCAP2, TRUE);
pGB->FindInterface(__uuidof(IVMRMixerControl9),(void**)&m_pMC, TRUE);




如果未找到 则用另外一种方法查找
if(!m_pCAP){
CComQIPtr<ISubPicAllocatorPresenter> pCAP = FindFilter(__uuidof(CSVPSubFilter), pGB);
if(pCAP){
m_pCAP = pCAP;
CComQIPtr<ISVPSubFilter> pSVPSub= pCAP;
if(pSVPSub)
m_pSVPSub = pSVPSub;
}
}


如果找到 则进行相关操作
if (m_pMC)
{
if (SetVMR9ColorControl(s.dBrightness, s.dContrast, s.dHue, s.dSaturation) == FALSE)
OsdMsg_SetShader();
else
{
CString szMsg;
szMsg.Format(ResStr(IDS_OSD_MSG_BRIGHT_CONTRAST_CHANGED), s.dBrightness, s.dContrast);
SendStatusMessage(szMsg, 3000);
}
SetShaders(true);
}


// === EVR !
pGB->FindInterface(__uuidof(IMFVideoDisplayControl), (void**)&m_pMFVDC, TRUE);
if (m_pMFVDC)
{
RECT Rect;
::GetClientRect (m_wndView.m_hWnd, &Rect);
m_pMFVDC->SetVideoWindow (m_wndView.m_hWnd);
m_pMFVDC->SetVideoPosition(NULL, &Rect);
}


打开终止异常
if(m_fOpeningAborted) throw aborted;


打开自定义大小的图像
OpenCustomizeGraph(); 待分析


打开终止异常
if(m_fOpeningAborted) throw aborted;


打开初始化视频
OpenSetupVideo(); 待分析


打开终止异常
if(m_fOpeningAborted) throw aborted;


打开初始化音频
OpenSetupAudio(); 待分析


打开终止异常
if(m_fOpeningAborted) throw aborted;


打开终止异常
if(m_fOpeningAborted) throw aborted;


改变声道
if(m_iAudioChannelMaping)
OnAudioChannalMapMenu(IDS_AUDIOCHANNALMAPNORMAL+m_iAudioChannelMaping); 待分析


加载完毕
m_iMediaLoadState = MLS_LOADED;


记录开始播放时间
time(&m_tPlayStartTime);


发送暂停消息
PostMessage(WM_COMMAND, ID_PLAY_PAUSE); 待分析


如果是打开 则发送播放消息
if(!(AfxGetAppSettings().nCLSwitches&CLSW_OPEN))
PostMessage(WM_COMMAND, ID_PLAY_PLAY); 待分析



AfxGetAppSettings().nCLSwitches &= ~CLSW_OPEN;


if(OpenFileData* p = dynamic_cast<OpenFileData*>(pOMD.m_p))
{
如果有记录 则跳到记录位置
if(p->rtStart > 0)
PostMessage(WM_RESUMEFROMSTATE, (WPARAM)PM_FILE, (LPARAM)(p->rtStart/10000)); // REFERENCE_TIME doesn't fit in LPARAM under a 32bit env.
}
else if(OpenDVDData* p = dynamic_cast<OpenDVDData*>(pOMD.m_p))
{
if(p->pDvdState)
PostMessage(WM_RESUMEFROMSTATE, (WPARAM)PM_DVD, (LPARAM)(CComPtr<IDvdState>(p->pDvdState).Detach())); // must be released by the called message handler
}
else if(OpenDeviceData* p = dynamic_cast<OpenDeviceData*>(pOMD.m_p))
{
m_wndCaptureBar.m_capdlg.SetVideoInput(p->vinput);
m_wndCaptureBar.m_capdlg.SetVideoChannel(p->vchannel);
m_wndCaptureBar.m_capdlg.SetAudioInput(p->ainput);
}




进行加载字幕
if(m_pCAP && (!m_fAudioOnly || m_fRealMediaGraph))
{
POSITION pos = pOMD->subs.GetHeadPosition();
while(pos){ LoadSubtitle(pOMD->subs.GetNext(pos));}
}


当前进程是不是主线程
if(::GetCurrentThreadId() == AfxGetApp()->m_nThreadID)
{
OnFilePostOpenmedia();
}
else
{
PostMessage(WM_COMMAND, ID_FILE_POST_OPENMEDIA); 待分析
}


初始化标题
OpenSetupWindowTitle(pOMD->title); 待分析


初始化打开时间
time_t tOpening = time(NULL);


当状态不是加载完成或正在加载 则循环 还在加载前则循环
while(m_iMediaLoadState != MLS_LOADED
&& m_iMediaLoadState != MLS_CLOSING // FIXME
)
{
if( (time(NULL) - tOpening) > 10)
throw aborted;
Sleep(50);
}
}
catch(LPCTSTR msg)
{
err = msg;
}
catch(CString msg)
{
err = msg;
}
}


if(!err.IsEmpty())
{
存在错误
SendStatusMessage(err, 3000);
CloseMediaPrivate();
m_closingmsg = err;


OpenFileData* p = dynamic_cast<OpenFileData*>(pOMD.m_p);
if(p && err != aborted)
{
m_wndPlaylistBar.SetCurValid(false);
if(m_wndPlaylistBar.GetCount() > 1)
{
CPlaylistItem pli[2];
m_wndPlaylistBar.GetCur(pli[0]);
m_wndPlaylistBar.SetNext();
m_wndPlaylistBar.GetCur(pli[1]);
if(pli[0].m_id != pli[1].m_id)
{
//CAutoPtr<OpenMediaData> p(m_wndPlaylistBar.GetCurOMD());
//if(p) OpenMediaPrivate(p);
}
}
}
}
else
{
m_wndPlaylistBar.SetCurValid(true); 列表设置
}


调用主线程更新的东西
PostMessage(WM_KICKIDLE); // calls main thread to update things


return(err.IsEmpty());
}


————————————————————————————————————————————
2.5秒 循环载入
case TIMER_LOADING:
{
KillTimer(TIMER_LOADING);
if (IsSomethingLoading())
{
SetTimer( TIMER_LOADING , 1000, NULL);
CString msg;
if (m_fBuffering)
{
BeginEnumFilters(pGB, pEF, pBF)
{
if (CComQIPtr<IAMNetworkStatus, &IID_IAMNetworkStatus> pAMNS = pBF)
{
long BufferingProgress = 0;
if (SUCCEEDED(pAMNS->get_BufferingProgress(&BufferingProgress)) && BufferingProgress > 0 && BufferingProgress < 99)
{
msg.Format(ResStr(IDS_CONTROLS_BUFFERING), BufferingProgress);
SendStatusMessage(msg,1000);
SVP_LogMsg5(msg);
}
break;
}
}
EndEnumFilters
}
else if (pAMOP)
{
__int64 t = 0, c = 0;
if (SUCCEEDED(pAMOP->QueryProgress(&t, &c)) && t > 0 && c < t)
{
msg.Format(ResStr(IDS_CONTROLS_BUFFERING), c*100/t);
SendStatusMessage(msg,1000);
SVP_LogMsg5(msg);
}
}
else
SendStatusMessage(ResStr(IDS_CONTROLS_OPENING), 1000);
}
}
break;






进入CMainFrame::OpenCreateGraphObject 分析
void CMainFrame::OpenCreateGraphObject(OpenMediaData* pOMD)
{
解码接口不为空
ASSERT(pGB == NULL);




m_fCustomGraph = false;
m_fRealMediaGraph = m_fShockwaveGraph = m_fQuicktimeGraph = false;


AppSettings& s = AfxGetAppSettings();


if(OpenFileData* p = dynamic_cast<OpenFileData*>(pOMD))
{
获得解码类型
engine_t engine = s.Formats.GetEngine(p->fns.GetHead());


std::wstring ct = ContentType::Get(p->fns.GetHead());


if(ct == L"video/x-ms-asf")
{
// TODO: put something here to make the windows media source filter load later
}
else if (ct == L"audio/x-pn-realaudio"
|| ct == L"audio/x-pn-realaudio-plugin"
|| ct == L"audio/x-realaudio-secure"
|| ct == L"video/vnd.rn-realvideo-secure"
|| ct == L"application/vnd.rn-realmedia"
|| ct.find(L"vnd.rn-") != ct.npos
|| ct.find(L"realaudio") != ct.npos
|| ct.find(L"realvideo") != ct.npos)
{
// TODO: go fuck this!!!
engine = RealMedia;
}
else if (ct == L"application/x-shockwave-flash")
{
engine = ShockWave;
}
else if (ct == L"video/quicktime"
|| ct == L"application/x-quicktimeplayer")
{
engine = QuickTime;
}
if (engine == RealMedia)
engine = DirectShow;


SVP_LogMsg5(L"got content type %s %d", ct.c_str(), engine );


HRESULT hr;
CComPtr<IUnknown> pUnk;


if(engine == RealMedia)
{
if(!(pUnk = (IUnknown*)(INonDelegatingUnknown*)new CRealMediaGraph(m_wndView.m_hWnd, hr)))
throw _T("Out of memory");


if(SUCCEEDED(hr) && !!(pGB = CComQIPtr<IGraphBuilder>(pUnk)))
m_fRealMediaGraph = true;
}
else if(engine == ShockWave)
{
if(!(pUnk = (IUnknown*)(INonDelegatingUnknown*)new CShockwaveGraph(m_wndView.m_hWnd, hr)))
throw _T("Out of memory");


if(FAILED(hr) || !(pGB = CComQIPtr<IGraphBuilder>(pUnk)))
throw _T("Can't create shockwave control");


m_fShockwaveGraph = true;
}
else if(engine == QuickTime)
{
if(!(pUnk = (IUnknown*)(INonDelegatingUnknown*)new CQuicktimeGraph(m_wndView.m_hWnd, hr)))
throw _T("Out of memory");


if(SUCCEEDED(hr) && !!(pGB = CComQIPtr<IGraphBuilder>(pUnk)))
m_fQuicktimeGraph = true;
}


m_fCustomGraph = m_fRealMediaGraph || m_fShockwaveGraph || m_fQuicktimeGraph;


if(!m_fCustomGraph)
{
视频播放解码 生成接口
pGB = new CFGManagerPlayer(_T("CFGManagerPlayer"), NULL, s.SrcFilters, s.TraFilters, m_wndView.m_hWnd);
}
}
else if(OpenDVDData* p = dynamic_cast<OpenDVDData*>(pOMD))
{
pGB = new CFGManagerDVD(_T("CFGManagerDVD"), NULL, s.SrcFilters, s.TraFilters, m_wndView.m_hWnd);
}
else if(OpenDeviceData* p = dynamic_cast<OpenDeviceData*>(pOMD))
{
pGB = new CFGManagerCapture(_T("CFGManagerCapture"), NULL, s.SrcFilters, s.TraFilters, m_wndView.m_hWnd);
}


if(!pGB)
{
throw _T("Failed to create the filter graph object");
}


pGB->AddToROT();


把视频解码接口赋值给其它
pMC = pGB; pME = pGB; pMS = pGB; // general
pVW = pGB; pBV = pGB; // video
pBA = pGB; // audio
pFS = pGB;


if(!(pMC && pME && pMS)
|| !(pVW && pBV)
|| !(pBA))
{
throw ResStr(IDS_MSG_THROW_BROKEN_DIRECTX_SUPPORT);
}


发送WM_GRAPHNOTIFY 消息
if(FAILED(pME->SetNotifyWindow((OAHWND)m_hWnd, WM_GRAPHNOTIFY, 0)))
{
throw _T("Could not set target window for graph notification");
}


m_pProv = (IUnknown*)new CKeyProvider(); 键盘提供者接口


if(CComQIPtr<IObjectWithSite> pObjectWithSite = pGB)
pObjectWithSite->SetSite(m_pProv); 键盘站点 捕获键盘消息


m_pCB = new CDSMChapterBag(NULL, NULL); dstuil库中类
}




进入OpenFile分析
void CMainFrame::OpenFile(OpenFileData* pOFD)
{
if(pOFD->fns.IsEmpty()) 文件为空 则抛出异常
throw _T("Invalid argument");


AppSettings& s = AfxGetAppSettings(); 获得设置信息


bool fFirst = true;


POSITION pos = pOFD->fns.GetHeadPosition();
while(pos)
{
CString fn = pOFD->fns.GetNext(pos);


fn.Trim();
if(fn.IsEmpty() && !fFirst)
break;


CString fnLower = fn;
fnLower.MakeLower();


HRESULT hr = -1;
如果不是mms://路径或mmsh://路径
if(FAILED(hr) && ( fnLower.Find(_T("mms://")) == 0 || fnLower.Find(_T("mmsh://")) == 0 )){ //
//render mms our own way
hr = OpenMMSUrlStream(fn);
}
if(FAILED(hr)) 渲染文件 持续了很长时间
hr = pGB->RenderFile(CStringW(fn), NULL);


如果是网络文件 则大概网络流
if(FAILED(hr) && ( fnLower.Find(_T("http") == 0 || fnLower.Find(_T("https://")) == 0
|| fnLower.Find(_T("udp://")) == 0 || fnLower.Find(_T("tcp://")) == 0)) ){ //
//render mms our own way
hr = OpenMMSUrlStream(fn);
}




/* not sure why this is not work for http youku etc 不知道这是为什么不适用于HTTP优酷等
HRESULT hr = -1;
if( ( fn.MakeLower().Find(_T("mms://")) == 0 || fn.MakeLower().Find(_T("mmsh://")) == 0 || (fn.MakeLower().Find(_T("http:")) == 0 && fn.MakeLower().Find(_T(":8902")) > 0 ))){
//render mms our own way
hr = OpenMMSUrlStream(fn);
}


if(FAILED(hr))
hr = pGB->RenderFile(CStringW(fn), NULL);
*/




依然失败 则寻找错误 记录错误
if(FAILED(hr))
{
if(fFirst)
{
//if(s.fReportFailedPins)
{
CComQIPtr<IGraphBuilderDeadEnd> pGBDE = pGB;
if(pGBDE && pGBDE->GetCount()) CMediaTypesDlg(pGBDE, this).DoModal();
}


CString err;


switch(hr)
{
case E_ABORT: err = ResStr(IDS_MSG_THROW_OPRATION_CANCELED); break;
case E_FAIL: case E_POINTER: default:
err.Format(ResStr(IDS_MSG_THROW_UNABLE_OPEN_FILE) , hr);
break;
case E_INVALIDARG: err = ResStr(IDS_MSG_THROW_ILLEGE_FILENAME); break;
case E_OUTOFMEMORY: err = ResStr(IDS_MSG_THROW_OUTOF_MEMORY); break;
case VFW_E_CANNOT_CONNECT: err = ResStr(IDS_MSG_THROW_UNABLE_DECODE); break;
case VFW_E_CANNOT_LOAD_SOURCE_FILTER: err = ResStr(IDS_MSG_THROW_UNSUPPORT_SOURCE); break;
case VFW_E_CANNOT_RENDER: err = ResStr(IDS_MSG_THROW_FAIL_CREATE_RENDER); break;
case VFW_E_INVALID_FILE_FORMAT: err = _T("Invalid file format"); break;
case VFW_E_NOT_FOUND: err = ResStr(IDS_MSG_THROW_FILE_NOT_FOUND); break;
case VFW_E_UNKNOWN_FILE_TYPE: err = ResStr(IDS_MSG_THROW_UNKNOWN_FILE_TYPE); break;
case VFW_E_UNSUPPORTED_STREAM: err = ResStr(IDS_MSG_THROW_UNSUPPORT_STREAM_TYPE); break;
}


throw err;
}
}


是否保存记录
if(s.fKeepHistory)
{
if(this->m_lastUrl == fn){ 本次与上次是否相同
CRecentFileList* pMRU = &s.MRUUrl;
pMRU->ReadList();
pMRU->Add(fn);
pMRU->WriteList();
this->m_lastUrl.Empty();
}else{
不同则写入
CRecentFileList* pMRU = fFirst ? &s.MRU : &s.MRUDub;
pMRU->ReadList();
pMRU->Add(fn);
pMRU->WriteList();
}
}


if(fFirst) 第一次运行? 搜索字幕
{
AppSettings& s = AfxGetAppSettings();
pOFD->title = fn;
m_fnCurPlayingFile = fn;
//是否有字幕? 沒有则下载字幕
CSVPToolBox svpTool;
//搜索目录下同名字幕
CAtlArray<CString> subSearchPaths;
subSearchPaths.Add(_T("."));
subSearchPaths.Add(s.GetSVPSubStorePath());
subSearchPaths.Add(svpTool.GetPlayerPath(L"SVPSub"));
subSearchPaths.Add(_T(".\\subtitles"));
subSearchPaths.Add(_T(".\\Subs"));
subSearchPaths.Add(_T("c:\\subtitles"));


CAtlArray<SubFile> ret;


POSITION pos = pOFD->subs.GetHeadPosition();
while(pos){
POSITION cur = pos;
CString szSubFn = pOFD->subs.GetNext(pos);
if(!svpTool.ifFileExist(szSubFn))
pOFD->subs.RemoveAt(cur);
}
CSVPRarLib svpRar;
if( svpRar.SplitPath(fn) ){
GetSubFileNames(svpRar.m_fnRAR, subSearchPaths, ret);
CAtlArray<SubFile> ret2;
GetSubFileNames(svpRar.m_fnInsideRar, subSearchPaths, ret2);
ret.Append(ret2);
}else{
GetSubFileNames(fn, subSearchPaths, ret);
//AfxMessageBox(fn);
}
for(int i = 0; i < ret.GetCount(); i++){
SubFile szBuf = ret.GetAt(i);
//AfxMessageBox(szBuf.fn);
if ( pOFD->subs.Find( szBuf.fn ) == NULL && svpTool.ifFileExist(szBuf.fn)){
pOFD->subs.AddTail(szBuf.fn);
//AfxMessageBox(szBuf.fn);
}
}
//AfxMessageBox(_T("1"));
if ( pOFD->subs.GetCount() <= 0){
// AfxMessageBox(_T("2"));




if(s.autoDownloadSVPSub){
CPath fPath(fn);
CString szExt;
szExt.Format(_T(" %s;"),fPath.GetExtension());
if(s.CheckSVPSubExts.Find(szExt) >= 0 ){
SVPSubDownloadByVPath(fn);
}else{
//SendStatusMessage( _T("正在播放的文件类型看来不需要字幕,终止自动智能匹配"), 1000);
}




}
}


}


fFirst = false;


if(m_fCustomGraph) break;
} 智能匹配字幕结束


//if(s.fReportFailedPins)
{ 如果绘图挂了 类型对话框弹出
CComQIPtr<IGraphBuilderDeadEnd> pGBDE = pGB;
if(pGBDE && pGBDE->GetCount()) CMediaTypesDlg(pGBDE, this).DoModal();
}


if(!(pAMOP = pGB))
{
BeginEnumFilters(pGB, pEF, pBF)
if(pAMOP = pBF) break;
EndEnumFilters
}


if(FindFilter(__uuidof(CShoutcastSource), pGB))
m_fUpdateInfoBar = true;


SetupChapters(); 初始化章节


枚举 寻找IKeyFrameInfo 接口
CComQIPtr<IKeyFrameInfo> pKFI;
BeginEnumFilters(pGB, pEF, pBF)
if(pKFI = pBF) break;
EndEnumFilters
UINT nKFs = 0, nKFsTmp = 0;
if(pKFI && S_OK == pKFI->GetKeyFrameCount(nKFs) && nKFs > 0)
{
m_kfs.SetCount(nKFsTmp = nKFs);
if(S_OK != pKFI->GetKeyFrames(&TIME_FORMAT_MEDIA_TIME, m_kfs.GetData(), nKFsTmp) || nKFsTmp != nKFs)
m_kfs.RemoveAll();
}


m_iPlaybackMode = PM_FILE;
}




进入SetupChapters() 初始化章节
void CMainFrame::SetupChapters()
{
ASSERT(m_pCB); 解码不为空


m_pCB->ChapRemoveAll();


查找过滤接口 并添加到pBFs
CInterfaceList<IBaseFilter> pBFs;
BeginEnumFilters(pGB, pEF, pBF)
pBFs.AddTail(pBF);
EndEnumFilters



POSITION pos;


循环遍历过滤接口 进行追加操作 具体什么 待分析
pos = pBFs.GetHeadPosition();
while(pos && !m_pCB->ChapGetCount())
{
IBaseFilter* pBF = pBFs.GetNext(pos);


CComQIPtr<IDSMChapterBag> pCB = pBF;
if(!pCB) continue;


for(DWORD i = 0, cnt = pCB->ChapGetCount(); i < cnt; i++)
{
REFERENCE_TIME rt;
CComBSTR name;
if(SUCCEEDED(pCB->ChapGet(i, &rt, &name)))
m_pCB->ChapAppend(rt, name);
}
}




循环遍历过滤接口 进行追加操作 具体什么 待分析
pos = pBFs.GetHeadPosition();
while(pos && !m_pCB->ChapGetCount())
{
IBaseFilter* pBF = pBFs.GetNext(pos);


CComQIPtr<IChapterInfo> pCI = pBF;
if(!pCI) continue;


CHAR iso6391[3];
::GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SISO639LANGNAME, iso6391, 3);
CStringA iso6392 = ISO6391To6392(iso6391);
if(iso6392.GetLength() < 3) iso6392 = "eng";


UINT cnt = pCI->GetChapterCount(CHAPTER_ROOT_ID);
for(UINT i = 1; i <= cnt; i++)
{
UINT cid = pCI->GetChapterId(CHAPTER_ROOT_ID, i);


ChapterElement ce;
if(pCI->GetChapterInfo(cid, &ce))
{
char pl[3] = {iso6392[0], iso6392[1], iso6392[2]};
char cc[] = " ";
CComBSTR name;
name.Attach(pCI->GetChapterStringInfo(cid, pl, cc));
m_pCB->ChapAppend(ce.rtStart, name);
}
}
}




循环遍历过滤接口 进行追加操作 具体什么 待分析
pos = pBFs.GetHeadPosition();
while(pos && !m_pCB->ChapGetCount())
{
IBaseFilter* pBF = pBFs.GetNext(pos);


CComQIPtr<IAMExtendedSeeking, &IID_IAMExtendedSeeking> pES = pBF;
if(!pES) continue;


long MarkerCount = 0;
if(SUCCEEDED(pES->get_MarkerCount(&MarkerCount)))
{
for(long i = 1; i <= MarkerCount; i++)
{
double MarkerTime = 0;
if(SUCCEEDED(pES->GetMarkerTime(i, &MarkerTime)))
{
CStringW name;
name.Format(L"Chapter %d", i);


CComBSTR bstr;
if(S_OK == pES->GetMarkerName(i, &bstr))
name = bstr;


m_pCB->ChapAppend(REFERENCE_TIME(MarkerTime*10000000), name);
}
}
}
}




循环遍历过滤接口 进行追加操作 具体什么 待分析
pos = pBFs.GetHeadPosition();
while(pos && !m_pCB->ChapGetCount())
{
IBaseFilter* pBF = pBFs.GetNext(pos);


if(GetCLSID(pBF) != CLSID_OggSplitter)
continue;


BeginEnumPins(pBF, pEP, pPin)
{
if(m_pCB->ChapGetCount()) break;


if(CComQIPtr<IPropertyBag> pPB = pPin)
{
for(int i = 1; ; i++)
{
CStringW str;
CComVariant var;


var.Clear();
str.Format(L"CHAPTER%02d", i);
if(S_OK != pPB->Read(str, &var, NULL))
break;


int h, m, s, ms;
WCHAR wc;
if(7 != swscanf(CStringW(var), L"%d%c%d%c%d%c%d", &h, &wc, &m, &wc, &s, &wc, &ms))
break;


CStringW name;
name.Format(L"Chapter %d", i);
var.Clear();
str += L"NAME";
if(S_OK == pPB->Read(str, &var, NULL))
name = var;


m_pCB->ChapAppend(10000i64*(((h*60 + m)*60 + s)*1000 + ms), name);
}
}
}
EndEnumPins
}


m_pCB->ChapSort();
}




进入OpenCustomizeGraph 自定义图像大小
void CMainFrame::OpenCustomizeGraph()
{
总共有enum {PM_NONE, PM_FILE, PM_DVD, PM_CAPTURE}种模式


PM_CAPTURE 模式 不支持自定义图像大小
if(m_iPlaybackMode == PM_CAPTURE) return;


CleanGraph(); 清楚画像


if(m_iPlaybackMode == PM_FILE) 文件模式
{
if(m_pCAP) {
if(AfxGetAppSettings().fAutoloadSubtitles) {
AddTextPassThruFilter(); 进行了很多连接 需要分析
}
}
}

同步视频
AppSettings& s = AfxGetAppSettings();
if (s.m_RenderSettings.bSynchronizeVideo)
{
HRESULT hr;
m_pRefClock = DNew CSyncClockFilter(NULL, &hr);
CStringW name;
name.Format(L"SyncClock Filter");
pGB->AddFilter(m_pRefClock, name);


CComPtr<IReferenceClock> refClock;
m_pRefClock->QueryInterface(IID_IReferenceClock, reinterpret_cast<void**>(&refClock));
CComPtr<IMediaFilter> mediaFilter;
pGB->QueryInterface(IID_IMediaFilter, reinterpret_cast<void**>(&mediaFilter));
mediaFilter->SetSyncSource(refClock);
mediaFilter = NULL;
refClock = NULL;


m_pRefClock->QueryInterface(IID_ISyncClock, reinterpret_cast<void**>(&m_pSyncClock));
}


BeginEnumFilters(pGB, pEF, pBF)
{
查找CLSID_OggSplitter 控件
if(GetCLSID(pBF) == CLSID_OggSplitter)
{
查找IAMStreamSelect接口
if(CComQIPtr<IAMStreamSelect> pSS = pBF)
{
LCID idAudio = AfxGetAppSettings().idAudioLang;
if(!idAudio) idAudio = GetUserDefaultLCID();
LCID idSub = AfxGetAppSettings().idSubtitlesLang;
if(!idSub) idSub = GetUserDefaultLCID();


DWORD cnt = 0;
pSS->Count(&cnt);
for(DWORD i = 0; i < cnt; i++)
{
AM_MEDIA_TYPE* pmt = NULL;
DWORD dwFlags = 0;
LCID lcid = 0;
DWORD dwGroup = 0;
WCHAR* pszName = NULL;
if(SUCCEEDED(pSS->Info((long)i, &pmt, &dwFlags, &lcid, &dwGroup, &pszName, NULL, NULL)))
{
CStringW name(pszName), sound(L"Sound"), subtitle(L"Subtitle");


if(idAudio != -1 && (idAudio&0x3ff) == (lcid&0x3ff) // sublang seems to be zeroed out in ogm...
&& name.GetLength() > sound.GetLength()
&& !name.Left(sound.GetLength()).CompareNoCase(sound))
{
if(SUCCEEDED(pSS->Enable(i, AMSTREAMSELECTENABLE_ENABLE)))
idAudio = -1;
}


if(idSub != -1 && (idSub&0x3ff) == (lcid&0x3ff) // sublang seems to be zeroed out in ogm...
&& name.GetLength() > subtitle.GetLength()
&& !name.Left(subtitle.GetLength()).CompareNoCase(subtitle)
&& name.Mid(subtitle.GetLength()).Trim().CompareNoCase(L"off"))
{
if(SUCCEEDED(pSS->Enable(i, AMSTREAMSELECTENABLE_ENABLE)))
idSub = -1;
}


if(pmt) DeleteMediaType(pmt);
if(pszName) CoTaskMemFree(pszName);
}
}
}
}
}
EndEnumFilters


CleanGraph();
}




进入OpenSetupVideo() 初始化视频
void CMainFrame::OpenSetupVideo()
{
只自动?
m_fAudioOnly = true;


if (m_pMFVDC) // EVR
{
EVR 不支持
m_fAudioOnly = false;
}
else if(m_pCAPR)
{
获得视频大小
CSize vs = m_pCAPR->GetVideoSize();
m_fAudioOnly = (vs.cx <= 0 || vs.cy <= 0);
}
else
{
否则其它
{
long w = 0, h = 0;


if(CComQIPtr<IBasicVideo> pBV = pGB)
{
pBV->GetVideoSize(&w, &h);
}


if(w > 0 && h > 0)
{
m_fAudioOnly = false;
}
}



if(m_fAudioOnly)
{
BeginEnumFilters(pGB, pEF, pBF)
{
long w = 0, h = 0;


if(CComQIPtr<IVideoWindow> pVW = pBF)
{
long lVisible;
if(FAILED(pVW->get_Visible(&lVisible)))
continue;


pVW->get_Width(&w);
pVW->get_Height(&h);
}


if(w > 0 && h > 0)
{
m_fAudioOnly = false;
break;
}
}
EndEnumFilters
}
}


if(m_fShockwaveGraph) flash控件
{
m_fAudioOnly = false;
}


if(m_pCAP)
{
SetShaders();
}
// else
{
// TESTME


pVW->put_Owner((OAHWND)m_wndView.m_hWnd);
pVW->put_WindowStyle(WS_CHILD|WS_CLIPSIBLINGS|WS_CLIPCHILDREN);
pVW->put_MessageDrain((OAHWND)m_hWnd);


for(CWnd* pWnd = m_wndView.GetWindow(GW_CHILD); pWnd; pWnd = pWnd->GetNextWindow())
pWnd->EnableWindow(FALSE); // little trick to let WM_SETCURSOR thru
}
}




进入SetShaders( BOOL silent ) 设置着色
void CMainFrame::SetShaders( BOOL silent )
{
if(!m_pCAPR) return; 不存在则直接返回


AppSettings& s = AfxGetAppSettings();


CAtlStringMap<const AppSettings::Shader*> s2s;


POSITION pos = s.m_shaders.GetHeadPosition();
while(pos)
{
const AppSettings::Shader* pShader = &s.m_shaders.GetNext(pos); 关键取值
s2s[pShader->label] = pShader;
}
if(!silent){
m_pCAPR->SetPixelShader(NULL, NULL);
if (m_pCAP2)
m_pCAP2->SetPixelShader2(NULL, NULL, true);


}


CAtlList<CString> labels;


pos = m_shaderlabels.GetHeadPosition();
while(pos)
{
const AppSettings::Shader* pShader = NULL;
if(s2s.Lookup(m_shaderlabels.GetNext(pos), pShader))
{
CStringA target = pShader->target;
CStringA srcdata = pShader->srcdata;


HRESULT hr = m_pCAPR->SetPixelShader(srcdata, target );


if(FAILED(hr))
{
//m_pCAP->SetPixelShader(NULL, NULL);
if (m_pCAP2)
hr = m_pCAP2->SetPixelShader2(srcdata, target, true);
if(FAILED(hr)){
// if (m_pCAP2)
// m_pCAP2->SetPixelShader2(NULL, NULL, true, !silent);
if(!silent)
{
CString label = pShader->label;
OsdMsg_SetShader(&label);
}
}
return;
}


labels.AddTail(pShader->label);
}
}


if(m_iMediaLoadState == MLS_LOADED)
{
CString str = Implode(labels, '|');
str.Replace(_T("|"), _T(", "));
if(!silent) SendStatusMessage(_T("Shader: ") + str, 3000);
}
if(!silent){
if (SetVMR9ColorControl(s.dBrightness , s.dContrast, 0, 0, true) == FALSE)
OsdMsg_SetShader();
}
}


进入OpenSetupAudio() 初始化音频
void CMainFrame::OpenSetupAudio()
{
赋值
pBA->put_Volume(m_wndToolBar.Volume);


// FIXME
// 又是从设置中取得数据
int balance = AfxGetAppSettings().nBalance;
int sign = balance>0?-1:1;
balance = max(100-abs(balance), 1);
balance = (int)((log10(1.0*balance)-2)*5000*sign);
balance = max(min(balance, 10000), -10000);
pBA->put_Balance(balance);
}






进入CMainFrame::OpenSetupWindowTitle 初始化标题
void CMainFrame::OpenSetupWindowTitle(CString fn)
{
CString title(MAKEINTRESOURCE(IDR_MAINFRAME));


AppSettings& s = AfxGetAppSettings();


int i = s.iTitleBarTextStyle;


if(!fn.IsEmpty() && (i == 0 || i == 1))
{
if(i == 1)
{
if(m_iPlaybackMode == PM_FILE)
{
fn.Replace('\\', '/');
CString fn2 = fn.Mid(fn.ReverseFind('/')+1);
if(!fn2.IsEmpty()) fn = fn2;


if(s.fTitleBarTextTitle)
{
BeginEnumFilters(pGB, pEF, pBF)
{
if(CComQIPtr<IAMMediaContent, &IID_IAMMediaContent> pAMMC = pBF)
{
CComBSTR bstr;
if(SUCCEEDED(pAMMC->get_Title(&bstr)) && bstr.Length())
{
fn = CString(bstr.m_str);
break;
}
}
}
EndEnumFilters
}
}
else if(m_iPlaybackMode == PM_DVD)
{
fn = _T("DVD");
}
else if(m_iPlaybackMode == PM_CAPTURE)
{
fn = _T("Live");
}
}


title = fn + _T(" - ") + title;
}
//CString szBuild;
//szBuild.Format(_T(" (Build %s)"),SVP_REV_STR);
//title += szBuild;
//SetWindowText(title);
m_szTitle = title;
RedrawNonClientArea();
}




在OpenMediaPrivate()中
PostMessage(WM_COMMAND, ID_PLAY_PAUSE);
if(!(AfxGetAppSettings().nCLSwitches&CLSW_OPEN))
PostMessage(WM_COMMAND, ID_PLAY_PLAY);




紧紧只是更新UI?
ON_UPDATE_COMMAND_UI(ID_PLAY_PLAY, OnUpdatePlayPauseStop)


进入OnUpdatePlayPauseStop 分析
void CMainFrame::OnUpdatePlayPauseStop(CCmdUI* pCmdUI)
{
OAFilterState fs = m_fFrameSteppingActive ? State_Paused : GetMediaState();


UI消息
pCmdUI->SetCheck(fs == State_Running && pCmdUI->m_nID == ID_PLAY_PLAY
|| fs == State_Paused && pCmdUI->m_nID == ID_PLAY_PAUSE
|| fs == State_Stopped && pCmdUI->m_nID == ID_PLAY_STOP
|| (fs == State_Paused || fs == State_Running) && pCmdUI->m_nID == ID_PLAY_PLAYPAUSE);


bool fEnable = false;


if(fs >= 0)
{
if(m_iPlaybackMode == PM_FILE || m_iPlaybackMode == PM_CAPTURE)
{
fEnable = true;


不能进入暂停状态,从停止使用rm
if(fs == State_Stopped && pCmdUI->m_nID == ID_PLAY_PAUSE && m_fRealMediaGraph) fEnable = false; // can't go into paused state from stopped with rm
else if(m_fCapturing) fEnable = false;
else if(m_fLiveWM && pCmdUI->m_nID == ID_PLAY_PAUSE) fEnable = false;
}
else if(m_iPlaybackMode == PM_DVD)
{
fEnable = m_iDVDDomain != DVD_DOMAIN_VideoManagerMenu
&& m_iDVDDomain != DVD_DOMAIN_VideoTitleSetMenu;


if(fs == State_Stopped && pCmdUI->m_nID == ID_PLAY_PAUSE) fEnable = false;
}
}
if(pCmdUI->m_nID == ID_PLAY_PLAY || pCmdUI->m_nID == ID_PLAY_PLAYPAUSE) fEnable = true;
pCmdUI->Enable(fEnable);
}




ON_COMMAND(ID_PLAY_PAUSE, OnPlayPause)
void CMainFrame::OnPlayPause()
//支持ffdshow的排队。
//为了避免暂停黑掉,我们以锁定g_ffdshowReceive同步与ReceiveMine的。
void CMainFrame::OnPlayPause()
{
// Support ffdshow queueing.
// To avoid black out on pause, we have to lock g_ffdshowReceive to synchronize with ReceiveMine.
time(&m_tPlayPauseTime);
if(queueu_ffdshow_support)
{
CAutoLock lck(&g_ffdshowReceive);
return OnPlayPauseI();
}
OnPlayPauseI();
}


进入OnPlayPauseI()分析
void CMainFrame::OnPlayPauseI()
{
if(m_iMediaLoadState == MLS_LOADED) 已经加载
{


if(m_iPlaybackMode == PM_FILE)
{
pMC->Pause(); 停止
}
else if(m_iPlaybackMode == PM_DVD)
{
pMC->Pause();
}
else if(m_iPlaybackMode == PM_CAPTURE)
{
pMC->Pause();
}


SetTimer(TIMER_STREAMPOSPOLLER, 40, NULL);
SetTimer(TIMER_STREAMPOSPOLLER2, 500, NULL);
SetTimer(TIMER_STATS, 1000, NULL);


KillTimer(TIMER_IDLE_TASK);
SetTimer(TIMER_IDLE_TASK, 30000, NULL);


SetAlwaysOnTop(AfxGetAppSettings().iOnTop); 设置置顶


}


MoveVideoWindow();
}


移动视频窗体
void CMainFrame::MoveVideoWindow(bool fShowStats)
{
视频已经加载 不是自动 窗体可见
if(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly && IsWindowVisible())
{


AppSettings &s = AfxGetAppSettings();
CRect wr;


if(!m_fFullScreen && (s.bUserAeroUI() || (!s.bUserAeroUI() && ( s.nCS & CS_TOOLBAR ))) )
{
m_wndView.GetClientRect(wr);


}
else
{
GetWindowRect(&wr);


// HACK
CRect r;
m_wndView.GetWindowRect(&r);
wr -= r.TopLeft();
}




CRect vr = CRect(0,0,0,0);


OAFilterState fs = GetMediaState();
if(fs == State_Paused || fs == State_Running || fs == State_Stopped && (m_fShockwaveGraph || m_fQuicktimeGraph))
{
CSize arxy = GetVideoSize();


int iDefaultVideoSize = AfxGetAppSettings().iDefaultVideoSize;


CSize ws =
iDefaultVideoSize == DVS_HALF ? CSize(arxy.cx/2, arxy.cy/2) :
iDefaultVideoSize == DVS_NORMAL ? arxy :
iDefaultVideoSize == DVS_DOUBLE ? CSize(arxy.cx*2, arxy.cy*2) :
wr.Size();


int w = ws.cx;
int h = ws.cy;


if(!m_fShockwaveGraph) //&& !m_fQuicktimeGraph)
{
if(iDefaultVideoSize == DVS_FROMINSIDE || iDefaultVideoSize == DVS_FROMOUTSIDE)
{
h = ws.cy;
w = MulDiv(h, arxy.cx, arxy.cy);


if(iDefaultVideoSize == DVS_FROMINSIDE && w > ws.cx
|| iDefaultVideoSize == DVS_FROMOUTSIDE && w < ws.cx)
{
w = ws.cx;
h = MulDiv(w, arxy.cy, arxy.cx);
}
}
}




CSize size(
(int)(m_ZoomX*w),
(int)(m_ZoomY*h));


CPoint pos(
(int)(m_PosX*(wr.Width()*3 - m_ZoomX*w) - wr.Width()),
(int)(m_PosY*(wr.Height()*3 - m_ZoomY*h) - wr.Height()));


/* CPoint pos(
(int)(m_PosX*(wr.Width() - size.cx)),
(int)(m_PosY*(wr.Height() - size.cy)));


*/
vr = CRect(pos, size);
}


wr |= CRect(0,0,0,0);
vr |= CRect(0,0,0,0);




//CString szLog;
//szLog.Format(_T("WVSize3 %d %d %d %d %d %d %d "), wr.Width(), wr.Height(), vr.Width(), vr.Height(), m_AngleX , m_AngleY , m_AngleZ);
//SVP_LogMsg(szLog);
if(m_pCAPR)
{
m_pCAPR->SetPosition(wr, vr);
m_pCAPR->SetVideoAngle(Vector(DegToRad(m_AngleX), DegToRad(m_AngleY), DegToRad(m_AngleZ)));
}
else
{
HRESULT hr;
hr = pBV->SetDefaultSourcePosition();
hr = pBV->SetDestinationPosition(vr.left, vr.top, vr.Width(), vr.Height());
hr = pVW->SetWindowPosition(wr.left, wr.top, wr.Width(), wr.Height());


if (m_pMFVDC) m_pMFVDC->SetVideoPosition (NULL, wr);
}
//SVP_LogMsg5(_T("MoveVideoWindow %d ") , wr.Height());
m_wndView.SetVideoRect(wr);


if(fShowStats && vr.Height() > 0)
{
CString info(L"正在使用智能拖拽功能。可在画面右上角进行拖拽");
// info.Format(_T("Pos %.2f %.2f, Zoom %.2f %.2f, AR %.2f"), m_PosX, m_PosY, m_ZoomX, m_ZoomY, (float)vr.Width()/vr.Height());
SendStatusMessage(info, 3000);
}
}
else
{
m_wndView.SetVideoRect();
}


CRect r;
m_wndView.GetClientRect(r);
if(m_iMediaLoadState == MLS_LOADED){
float fViewRatio = (float)r.Width() / r.Height();
CSize vsize = GetVideoSize();
float fVideoRatio = (float)vsize.cx / vsize.cy;
m_fScreenHigherThanVideo = (fViewRatio < fVideoRatio );


}
}






仅仅只是更新UI
void CMainFrame::OnUpdatePlayPauseStop(CCmdUI* pCmdUI)
{
OAFilterState fs = m_fFrameSteppingActive ? State_Paused : GetMediaState();


pCmdUI->SetCheck(fs == State_Running && pCmdUI->m_nID == ID_PLAY_PLAY
|| fs == State_Paused && pCmdUI->m_nID == ID_PLAY_PAUSE
|| fs == State_Stopped && pCmdUI->m_nID == ID_PLAY_STOP
|| (fs == State_Paused || fs == State_Running) && pCmdUI->m_nID == ID_PLAY_PLAYPAUSE);


bool fEnable = false;


if(fs >= 0)
{
if(m_iPlaybackMode == PM_FILE || m_iPlaybackMode == PM_CAPTURE)
{
fEnable = true;


if(fs == State_Stopped && pCmdUI->m_nID == ID_PLAY_PAUSE && m_fRealMediaGraph) fEnable = false; // can't go into paused state from stopped with rm
else if(m_fCapturing) fEnable = false;
else if(m_fLiveWM && pCmdUI->m_nID == ID_PLAY_PAUSE) fEnable = false;
}
else if(m_iPlaybackMode == PM_DVD)
{
fEnable = m_iDVDDomain != DVD_DOMAIN_VideoManagerMenu
&& m_iDVDDomain != DVD_DOMAIN_VideoTitleSetMenu;


if(fs == State_Stopped && pCmdUI->m_nID == ID_PLAY_PAUSE) fEnable = false;
}
}
if(pCmdUI->m_nID == ID_PLAY_PLAY || pCmdUI->m_nID == ID_PLAY_PLAYPAUSE) fEnable = true;
pCmdUI->Enable(fEnable);
}






// play 播放事件
void CMainFrame::OnPlayPlay()
{
if(m_iMediaLoadState == MLS_LOADED) 必须载入
{
if(GetMediaState() == State_Stopped) { m_iSpeedLevel = 0; time(&m_tPlayStartTime);} 记录


try
{


if(m_iPlaybackMode == PM_FILE) 文件格式
{
time_t ttNow;
time(&ttNow);
if( m_tPlayPauseTime > m_tPlayStartTime){
m_tPlayStartTime += (ttNow - m_tPlayPauseTime);
}
if(m_fEndOfStream){ 如果文件流没有 则停止
SendMessage(WM_COMMAND, ID_PLAY_STOP);
Sleep(1500);
}
pMC->Run(); 运行
}
else if(m_iPlaybackMode == PM_DVD) DVD格式
{
double dRate = 1.0;
//if(m_iSpeedLevel != -4 && m_iSpeedLevel != 0)
// dRate = pow(2.0, m_iSpeedLevel >= -3 ? m_iSpeedLevel : (-m_iSpeedLevel - 8));
dRate = 1.0 + m_iSpeedLevel * 0.1;


pDVDC->PlayForwards(dRate, DVD_CMD_FLAG_Block, NULL);
pDVDC->Pause(FALSE);
pMC->Run();
}
else if(m_iPlaybackMode == PM_CAPTURE) CAPTURE 格式
{
pMC->Stop(); // audio preview won't be in sync if we run it from paused state
pMC->Run();
}
}
catch (...)
{
SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA); 异常 就关闭视频
return;
}
SetTimer(TIMER_STREAMPOSPOLLER, 40, NULL); 位置信息
SetTimer(TIMER_STREAMPOSPOLLER2, 500, NULL); 位置2信息
SetTimer(TIMER_STATS, 1000, NULL); 状态信息


if(m_fFrameSteppingActive) // FIXME 第一次 设置声音
{
m_fFrameSteppingActive = false;
pBA->put_Volume(m_VolumeBeforeFrameStepping);
}


SetAlwaysOnTop(AfxGetAppSettings().iOnTop); 置顶


m_wndColorControlBar.CheckAbility(); 控件状态位置等信息


MoveVideoWindow(); 移动视频
}else if(m_iMediaLoadState == MLS_CLOSED){ 如果是关闭状态 则重新播放
if(m_WndSizeInited >= 2){
if(m_wndPlaylistBar.GetCount()){
OpenCurPlaylistItem();
//}else
// SendMessage(WM_COMMAND, ID_FILE_OPENMEDIA);
}
}


}
//KillTimer(TIMER_SNAP);
//SetTimer(TIMER_SNAP, 10000, NULL);
}




进入OnFilePostOpenmedia() 分析
void CMainFrame::OnFilePostOpenmedia()
{


OpenSetupClipInfo(); 初始化剪切板信息


//A-B Control
m_aRefTime = 0;
m_bRefTime = 0;
ABControlOn = FALSE;


OpenSetupCaptureBar(); 初始化控件


AppSettings& s = AfxGetAppSettings();
m_wndColorControlBar.CheckAbility(); 检查能力


if(m_wndToolBar.IsVisible())
ShowControls(AfxGetAppSettings().nCS | CS_SEEKBAR, false); 显示控件


__int64 rtDur = 0;
pMS->GetDuration(&rtDur); 从视频接口获得当前位置
m_wndPlaylistBar.SetCurTime(rtDur); 设置控件位置


if(m_iPlaybackMode == PM_CAPTURE)
{
ShowControlBar(&m_wndPlaylistBar, FALSE, TRUE);
ShowControlBar(&m_wndCaptureBar, TRUE, TRUE);
}



/ /重要:不能调用任何窗口封邮件之前
/ /这一点上,它会僵局时OpenMediaPrivate
/ /仍在运行,并创建渲染窗口
/ /相同的工作者线程
std::wstring szFileHash = HashController::GetInstance()->GetSPHash(m_fnCurPlayingFile);


CString FPath = szFileHash.c_str();


加载第二字幕
if(m_pCAP && (!m_fAudioOnly || m_fRealMediaGraph))
{
if(m_pSubStreams.GetCount() == 0){
if ( !m_wndPlaylistBar.m_pl.szPlayListSub.IsEmpty() ){
int delayms = 0 - m_wndPlaylistBar.GetTotalTimeBeforeCur();


LoadSubtitle(m_wndPlaylistBar.m_pl.szPlayListSub, delayms , true);
}
}


if(s.fEnableSubtitles && m_pSubStreams.GetCount() > 0){
BOOL HavSubs1 = FALSE;


Sql 操作 搜索历史记录
if(AfxGetMyApp()->sqlite_local_record ){
CString szSQL;
szSQL.Format(L"SELECT subid FROM histories WHERE fpath = \"%s\" ", FPath);
int subid = AfxGetMyApp()->sqlite_local_record->get_single_int_from_sql(szSQL.GetBuffer(), -1);
if(subid >= 0){
//SVP_LogMsg5(L"subid %d %d", subid, m_pSubStreams.GetCount());


int i = subid;




字幕流?
POSITION pos = m_pSubStreams.GetHeadPosition();
while(pos && i >= 0)
{
循环查找
CComPtr<ISubStream> pSubStream = m_pSubStreams.GetNext(pos);


if(i < pSubStream->GetStreamCount())
{
SendStatusMessage(ResStr(IDS_OSD_MSG_RESTORE_TO_LAST_REMEMBER_SUBTITLE_TRACK),3000);
CAutoLock cAutoLock(&m_csSubLock);
pSubStream->SetStream(i);
SetSubtitle(pSubStream);
HavSubs1 = true;
break;
}


i -= pSubStream->GetStreamCount();
}


}
}


字幕流?
if(!HavSubs1 && !s.sSubStreamName1.IsEmpty()){


POSITION pos = m_pSubStreams.GetHeadPosition();
while(pos){
CComPtr<ISubStream> pSubStream = m_pSubStreams.GetNext(pos);


if(!pSubStream) continue;


for(int i = 0, j = pSubStream->GetStreamCount(); i < j; i++)
{
WCHAR* pName = NULL;
if(SUCCEEDED(pSubStream->GetStreamInfo(i, &pName, NULL)))
{
CString name(pName);
//SVP_LogMsg5(L"sub2 %s", name);
if( name == s.sSubStreamName1){
SetSubtitle( pSubStream);
HavSubs1 = true;
}
CoTaskMemFree(pName);
if(HavSubs1)
break;
}


}
if(HavSubs1)
break;
}
}


设置字幕流
if(!HavSubs1){
POSITION pos = m_pSubStreams.GetHeadPosition();
while(pos){
CComPtr<ISubStream> pSubStream = m_pSubStreams.GetNext(pos);


if(!pSubStream) continue;


for(int i = 0, j = pSubStream->GetStreamCount(); i < j; i++)
{
WCHAR* pName = NULL;
if(SUCCEEDED(pSubStream->GetStreamInfo(i, &pName, NULL)))
{
CString name(pName);
//SVP_LogMsg5(L"sub2 %s", name);
if( name.Find(L"plain text") > 0){ //Apple Text Media Handler (plain text)
SetSubtitle( pSubStream);
HavSubs1 = true;
}
CoTaskMemFree(pName);
if(HavSubs1)
break;
}


}
if(HavSubs1)
break;
}
}


字幕流
if(!HavSubs1)
SetSubtitle(m_pSubStreams.GetHead());


if(s.fAutoloadSubtitles2 && m_pSubStreams2.GetCount() > 1 ){
BOOL HavSubs = false;


if(AfxGetMyApp()->sqlite_local_record ){
CString szSQL;
szSQL.Format(L"SELECT subid2 FROM histories WHERE fpath = \"%s\" ", FPath);
int subid = AfxGetMyApp()->sqlite_local_record->get_single_int_from_sql(szSQL.GetBuffer(), -1);
if(subid >= 0){
//SVP_LogMsg5(L"subid %d %d", subid, m_pSubStreams.GetCount());


int i = subid;


POSITION pos = m_pSubStreams2.GetHeadPosition();
while(pos && i >= 0)
{
CComPtr<ISubStream> pSubStream = m_pSubStreams2.GetNext(pos);


if(i < pSubStream->GetStreamCount())
{
CAutoLock cAutoLock(&m_csSubLock);
pSubStream->SetStream(i);
SetSubtitle2(pSubStream);
//SendStatusMessage(ResStr(IDS_OSD_MSG_RESTORE_TO_LAST_REMEMBER_SUBTITLE2_TRACK),3000);
HavSubs = true;
break;
}


i -= pSubStream->GetStreamCount();
}


}
}




字幕流
if(!HavSubs && !s.sSubStreamName2.IsEmpty()){
POSITION pos = m_pSubStreams2.GetHeadPosition();
while(pos){
CComPtr<ISubStream> pSubStream = m_pSubStreams2.GetNext(pos);


if(!pSubStream) continue;


for(int i = 0, j = pSubStream->GetStreamCount(); i < j; i++)
{
WCHAR* pName = NULL;
if(SUCCEEDED(pSubStream->GetStreamInfo(i, &pName, NULL)))
{
CString name(pName);
//SVP_LogMsg5(L"sub2 %s", name);
if((!s.sSubStreamName2.IsEmpty() && name == s.sSubStreamName2) ){
SetSubtitle2( pSubStream);
HavSubs = true;
}
CoTaskMemFree(pName);
if(HavSubs)
break;
}


}
if(HavSubs)
break;
}
}


字幕流
if(!HavSubs){
POSITION pos = m_pSubStreams2.GetHeadPosition();
while(pos){
CComPtr<ISubStream> pSubStream = m_pSubStreams2.GetNext(pos);


if(!pSubStream) continue;


for(int i = 0, j = pSubStream->GetStreamCount(); i < j; i++)
{
WCHAR* pName = NULL;
if(SUCCEEDED(pSubStream->GetStreamInfo(i, &pName, NULL)))
{
CString name(pName);
//SVP_LogMsg5(L"sub2 %s", name);
if( ( name.Find(_T("en")) >= 0 || name.Find(_T("eng")) >= 0 || name.Find(_T("英文")) >= 0) ){
SetSubtitle2( pSubStream);
HavSubs = true;
}
CoTaskMemFree(pName);
if(HavSubs)
break;
}


}
if(HavSubs)
break;
}
}
if(!HavSubs){
POSITION pos = m_pSubStreams2.GetHeadPosition();
m_pSubStreams2.GetNext(pos);
if(pos)
SetSubtitle2( m_pSubStreams2.GetNext(pos));
}


}
}


//make sure the subtitle displayed
UpdateSubtitle(true); 设置字幕流
UpdateSubtitle2(true); 设置字幕流
}


根据Sql查找历史 发送状态
if(AfxGetMyApp()->sqlite_local_record ){
CString szSQL;
szSQL.Format(L"SELECT audioid FROM histories WHERE fpath = \"%s\" ", FPath);
//SVP_LogMsg5(szSQL);
int audid = AfxGetMyApp()->sqlite_local_record->get_single_int_from_sql(szSQL.GetBuffer(), -1);
if(audid > 0){
SVP_LogMsg5(L"audid %d subs %d", audid, m_pSubStreams.GetCount());
CComQIPtr<IAMStreamSelect> pSS = FindFilter(__uuidof(CAudioSwitcherFilter), pGB);
if(!pSS) pSS = FindFilter(L"{D3CD7858-971A-4838-ACEC-40CA5D529DC8}", pGB);
if( pSS)
{
pSS->Enable(audid, AMSTREAMSELECTENABLE_ENABLE);
SendStatusMessage(ResStr(IDS_OSD_MSG_RESTORE_TO_LAST_REMEMBER_AUDIO_TRACK),3000);
}
}
}




根据SQL 设置字幕
if (AfxGetMyApp()->sqlite_local_record)
{
CString szSQL;
if (s.fEnableSubtitles ){
szSQL.Format(L"SELECT subid FROM histories_stream WHERE fpath = \"%s\" ", FPath);
int subid = AfxGetMyApp()->sqlite_local_record->get_single_int_from_sql(szSQL.GetBuffer(), -1);
if(subid > 0){
OnPlayLanguage(subid);
}
}
szSQL.Format(L"SELECT audioid FROM histories_stream WHERE fpath = \"%s\" ", FPath);
int audid = AfxGetMyApp()->sqlite_local_record->get_single_int_from_sql(szSQL.GetBuffer(), -1);
if(audid > 0){
OnPlayLanguage(audid);
}
}


if(!m_pCAP && m_fAudioOnly){ / /这是我们第一次检测,这是仅音频文件


m_wndView.m_strAudioInfo.Empty();
//This is silly
if(!m_fLastIsAudioOnly)
ShowControlBar(&m_wndPlaylistBar, FALSE, TRUE);


KillTimer(TIMER_TRANSPARENTTOOLBARSTAT);
SetTimer(TIMER_TRANSPARENTTOOLBARSTAT, 20,NULL);
rePosOSD(); 重新计算位置
}


{
WINDOWPLACEMENT wp;
wp.length = sizeof(wp);
GetWindowPlacement(&wp); 记录窗体位置


// restore magnification 只有音频的情况下
if(IsWindowVisible() && AfxGetAppSettings().fRememberZoomLevel
&& !(m_fFullScreen || wp.showCmd == SW_SHOWMAXIMIZED || wp.showCmd == SW_SHOWMINIMIZED))
{
if(m_fAudioOnly && m_fLastIsAudioOnly){






}else{
ZoomVideoWindow(); 全屏播放


// m_fFullScreen意思现在是指当前播放模式是全屏还是非全屏,如果是全屏就会在Toogle中变为非全屏,反之亦然
if (!m_fFullScreen)
{
PlayerPreference* pref = PlayerPreference::GetInstance();
bool bToBeFullScreen = pref->GetIntVar(INTVAR_TOGGLEFULLSCRENWHENPLAYBACKSTARTED);
if (bToBeFullScreen) 是否全屏
{
ToggleFullscreen(true, true);
SetCursor(NULL);
}
}
}
m_fLastIsAudioOnly = m_fAudioOnly;


}
}


if(!m_fAudioOnly && (s.nCLSwitches&CLSW_FULLSCREEN)) 全屏时
{
SendMessage(WM_COMMAND, ID_VIEW_FULLSCREEN);
s.nCLSwitches &= ~CLSW_FULLSCREEN;
}


m_bDxvaInUse = false;
m_bMustUseExternalTimer = false;
m_haveSubVoted = false;
m_DXVAMode = _T("");
视频解码接口
CComQIPtr<IMPCVideoDecFilter> pMDF = FindFilter(__uuidof(CMPCVideoDecFilter), pGB);
if(pMDF){
GUID* DxvaGui = NULL;
DxvaGui = pMDF->GetDXVADecoderGuid();
if (DxvaGui != NULL)
{
m_DXVAMode = GetDXVAMode (DxvaGui);
m_bDxvaInUse = (m_DXVAMode != _T("Not using DXVA"));


}


}else if(FindFilter(L"{09571A4B-F1FE-4C60-9760-DE6D310C7C31}", pGB)) {
if(s.bHasCUDAforCoreAVC){
m_bDxvaInUse = true;
m_DXVAMode = _T("CoreAVC");
}


}
/*
CComQIPtr<IWMReaderAdvanced2> pWMR = FindFilter(__uuidof(IWMReaderAdvanced2), pGB);
if(pWMR){
pWMR->SetPlayMode(WMT_PLAY_MODE_STREAMING);
AfxMessageBox(L"1");
}*/
if(FindFilter(L"{FA10746C-9B63-4B6C-BC49-FC300EA5F256}", pGB)){
m_bEVRInUse = true;
}
if( FindFilter(L"{6F513D27-97C3-453C-87FE-B24AE50B1601}", pGB)){//m_bEVRInUse
SVP_LogMsg5(L"Has Divx H264 Dec and EVR so use External Timer");
m_bMustUseExternalTimer = true;
}


RedrawNonClientArea(); 重新绘画客户区




if(m_iPlaybackMode == PM_FILE){ 回放模式
if(!s.bDontNeedSVPSubFilter && !m_pCAP && s.iSVPRenderType && !m_fAudioOnly ){
s.iSVPRenderType = 0;
SendStatusMessage( ResStr(IDS_OSD_MSG_DEVICE_NOT_SUPPORT_VIDEO_QMODE), 2000);
}


if(m_fAudioOnly && m_fnCurPlayingFile.Find(L"://") < 0){
只有音频时 查找歌词
//find lyric file
m_LyricFilePaths.RemoveAll();
CAtlArray<CString> lrcSearchPaths;
lrcSearchPaths.Add(_T("."));
lrcSearchPaths.Add(s.GetSVPSubStorePath());


CAtlArray<LrcFile> ret;
int bGotLrc = 0 ;
m_Lyric.GetLrcFileNames( m_fnCurPlayingFile , lrcSearchPaths, ret);
if( ret.GetCount() ){
LrcFile oLrcFile = ret.GetAt(0);
if( m_Lyric.LoadLyricFile( oLrcFile.fn) >= 0) 装载歌词
{
//maybe we should do something here?
if(m_Lyric.m_has_lyric)
bGotLrc = 1;
}


}
if( !bGotLrc && s.autoDownloadSVPSub ) { 没有歌词 但自动下载
//debug
//m_Lyric.LoadLyricFile(L"D:\\-=SVN=-\\test.lrc");


m_Lyric.Empty();
//download it by thead
m_Lyric.title = GetClipInfo(IDS_INFOBAR_TITLE).c_str();
m_Lyric.artist = GetClipInfo(IDS_INFOBAR_AUTHOR).c_str();
m_Lyric.album = GetClipInfo(IDS_INFOBAR_DESCRIPTION).c_str();


m_Lyric.m_sz_current_music_file = m_fnCurPlayingFile;


//m_Lyric.m_stop_downloading = 1;
//TerminateThread(m_lyricDownloadThread , 0);
启动线程下载
m_lyricDownloadThread = AfxBeginThread(lyric_fetch_Proc, &m_Lyric, THREAD_PRIORITY_LOWEST, 0, CREATE_SUSPENDED);
m_lyricDownloadThread->m_pMainWnd = AfxGetMainWnd();
m_lyricDownloadThread->ResumeThread();


}




}


}


// send sphash to remote 发送sphash到远程
m_wndToolBar.HideMovieShareBtn(TRUE);
UserShareController::GetInstance()->HideCommentPlane();
UserShareController::GetInstance()->CloseShooterMedia();
if(IsSomethingLoaded() && !m_fAudioOnly && (UINT)((INT64)rtDur/10000000) > 90)
{
m_movieShared = false;
m_wndToolBar.HideMovieShareBtn(FALSE);
SetTimer(TIMER_MOVIESHARE, 300000, NULL);
}


KillTimer(TIMER_IDLE_TASK);
}




进入CMainFrame::OpenSetupCaptureBar 分析
void CMainFrame::OpenSetupCaptureBar() 初始化头导航
{


初始化控件
if(m_iPlaybackMode == PM_CAPTURE)
{
if(pVidCap && pAMVSCCap)
{
CComQIPtr<IAMVfwCaptureDialogs> pVfwCD = pVidCap;


if(!pAMXBar && pVfwCD)
{
m_wndCaptureBar.m_capdlg.SetupVideoControls(m_VidDispName, pAMVSCCap, pVfwCD);
}
else
{
m_wndCaptureBar.m_capdlg.SetupVideoControls(m_VidDispName, pAMVSCCap, pAMXBar, pAMTuner);
}
}


if(pAudCap && pAMASC)
{
CInterfaceArray<IAMAudioInputMixer> pAMAIM;


BeginEnumPins(pAudCap, pEP, pPin)
{
if(CComQIPtr<IAMAudioInputMixer> pAIM = pPin)
pAMAIM.Add(pAIM);
}
EndEnumPins


m_wndCaptureBar.m_capdlg.SetupAudioControls(m_AudDispName, pAMASC, pAMAIM);
}
}


BuildGraphVideoAudio(
m_wndCaptureBar.m_capdlg.m_fVidPreview, false,
m_wndCaptureBar.m_capdlg.m_fAudPreview, false);
}






进入CMainFrame::BuildGraphVideoAudio 分析
bool CMainFrame::BuildGraphVideoAudio(int fVPreview, bool fVCapture, int fAPreview, bool fACapture)
{
if(!pCGB) return(false); 不存在直接返回 关键是pCGB另一个


SaveMediaState;


HRESULT hr;


pGB->NukeDownstream(pVidCap);
pGB->NukeDownstream(pAudCap);


CleanGraph();


if(pAMVSCCap) hr = pAMVSCCap->SetFormat(&m_wndCaptureBar.m_capdlg.m_mtv);
if(pAMVSCPrev) hr = pAMVSCPrev->SetFormat(&m_wndCaptureBar.m_capdlg.m_mtv);
if(pAMASC) hr = pAMASC->SetFormat(&m_wndCaptureBar.m_capdlg.m_mta);


CComPtr<IBaseFilter> pVidBuffer = m_wndCaptureBar.m_capdlg.m_pVidBuffer;
CComPtr<IBaseFilter> pAudBuffer = m_wndCaptureBar.m_capdlg.m_pAudBuffer;
CComPtr<IBaseFilter> pVidEnc = m_wndCaptureBar.m_capdlg.m_pVidEnc;
CComPtr<IBaseFilter> pAudEnc = m_wndCaptureBar.m_capdlg.m_pAudEnc;
CComPtr<IBaseFilter> pMux = m_wndCaptureBar.m_capdlg.m_pMux;
CComPtr<IBaseFilter> pDst = m_wndCaptureBar.m_capdlg.m_pDst;
CComPtr<IBaseFilter> pAudMux = m_wndCaptureBar.m_capdlg.m_pAudMux;
CComPtr<IBaseFilter> pAudDst = m_wndCaptureBar.m_capdlg.m_pAudDst;


bool fFileOutput = (pMux && pDst) || (pAudMux && pAudDst);
bool fCapture = (fVCapture || fACapture);


if(pAudCap)
{
AM_MEDIA_TYPE* pmt = &m_wndCaptureBar.m_capdlg.m_mta;
int ms = (fACapture && fFileOutput && m_wndCaptureBar.m_capdlg.m_fAudOutput) ? AUDIOBUFFERLEN : 60;
if(pMux != pAudMux && fACapture) SetLatency(pAudCap, -1);
else if(pmt->pbFormat) SetLatency(pAudCap, ((WAVEFORMATEX*)pmt->pbFormat)->nAvgBytesPerSec * ms / 1000);
}


CComPtr<IPin> pVidCapPin, pVidPrevPin, pAudCapPin, pAudPrevPin;
BuildToCapturePreviewPin(pVidCap, &pVidCapPin, &pVidPrevPin, pAudCap, &pAudCapPin, &pAudPrevPin);


// if(pVidCap)
{
bool fVidPrev = pVidPrevPin && fVPreview;
bool fVidCap = pVidCapPin && fVCapture && fFileOutput && m_wndCaptureBar.m_capdlg.m_fVidOutput;


if(fVPreview == 2 && !fVidCap && pVidCapPin)
{
pVidPrevPin = pVidCapPin;
pVidCapPin = NULL;
}


if(fVidPrev)
{
m_pCAP = NULL;
m_pCAP2 = NULL;
m_pCAPR = NULL;
pGB->Render(pVidPrevPin);
pGB->FindInterface(__uuidof(ISubPicAllocatorPresenter), (void**)&m_pCAP, FALSE);
pGB->FindInterface(__uuidof(ISubPicAllocatorPresenterRender), (void**)&m_pCAPR, TRUE);
pGB->FindInterface(__uuidof(ISubPicAllocatorPresenter2), (void**)&m_pCAP2, TRUE);
}


if(fVidCap)
{
IBaseFilter* pBF[3] = {pVidBuffer, pVidEnc, pMux};
HRESULT hr = BuildCapture(pVidCapPin, pBF, MEDIATYPE_Video, &m_wndCaptureBar.m_capdlg.m_mtcv);
}


pAMDF = NULL;
pCGB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pVidCap, IID_IAMDroppedFrames, (void**)&pAMDF);
}


// if(pAudCap)
{
bool fAudPrev = pAudPrevPin && fAPreview;
bool fAudCap = pAudCapPin && fACapture && fFileOutput && m_wndCaptureBar.m_capdlg.m_fAudOutput;


if(fAPreview == 2 && !fAudCap && pAudCapPin)
{
pAudPrevPin = pAudCapPin;
pAudCapPin = NULL;
}


if(fAudPrev)
{
pGB->Render(pAudPrevPin);
}


if(fAudCap)
{
IBaseFilter* pBF[3] = {pAudBuffer, pAudEnc, pAudMux ? pAudMux : pMux};
HRESULT hr = BuildCapture(pAudCapPin, pBF, MEDIATYPE_Audio, &m_wndCaptureBar.m_capdlg.m_mtca);
}
}


if((pVidCap || pAudCap) && fCapture && fFileOutput)
{
if(pMux != pDst)
{
hr = pGB->AddFilter(pDst, L"File Writer V/A");
hr = pGB->ConnectFilter(GetFirstPin(pMux, PINDIR_OUTPUT), pDst);
}


if(CComQIPtr<IConfigAviMux> pCAM = pMux)
{
int nIn, nOut, nInC, nOutC;
CountPins(pMux, nIn, nOut, nInC, nOutC);
pCAM->SetMasterStream(nInC-1);
// pCAM->SetMasterStream(-1);
pCAM->SetOutputCompatibilityIndex(FALSE);
}


if(CComQIPtr<IConfigInterleaving> pCI = pMux)
{
// if(FAILED(pCI->put_Mode(INTERLEAVE_CAPTURE)))
if(FAILED(pCI->put_Mode(INTERLEAVE_NONE_BUFFERED)))
pCI->put_Mode(INTERLEAVE_NONE);


REFERENCE_TIME rtInterleave = 10000i64*AUDIOBUFFERLEN, rtPreroll = 0;//10000i64*500
pCI->put_Interleaving(&rtInterleave, &rtPreroll);
}


if(pMux != pAudMux && pAudMux != pAudDst)
{
hr = pGB->AddFilter(pAudDst, L"File Writer A");
hr = pGB->ConnectFilter(GetFirstPin(pAudMux, PINDIR_OUTPUT), pAudDst);
}
}


REFERENCE_TIME stop = MAX_TIME;
hr = pCGB->ControlStream(&PIN_CATEGORY_CAPTURE, NULL, NULL, NULL, &stop, 0, 0); // stop in the infinite


CleanGraph();


OpenSetupVideo();
OpenSetupAudio();


RestoreMediaState;


return(true);
}




OnFilePostOpenmedia() 中 SetTimer(TIMER_MOVIESHARE, 300000, NULL);
case TIMER_MOVIESHARE:
{
KillTimer(TIMER_MOVIESHARE);
if (IsSomethingLoaded() && !m_fAudioOnly && !m_movieShared) 已经加载 不是音频 文件不共享
{
m_movieShared = true;
std::wstring uuid, moviehash;
SPlayerGUID::GenerateGUID(uuid);
UserShareController* usc = UserShareController::GetInstance();
usc->CreateCommentPlane();
moviehash = HashController::GetInstance()->GetSPHash(m_fnCurPlayingFile);
usc->ShareMovie(uuid, moviehash, m_fnCurPlayingFile.GetString());
}
}
break;






进入CMainFrame::ZoomVideoWindow 分析
void CMainFrame::ZoomVideoWindow(double scale)
{
if(m_iMediaLoadState != MLS_LOADED) return; 没有装载 直接退出 ?




AppSettings& s = AfxGetAppSettings();


if(s.bUserAeroUI()){ 用户区域UI
m_lTransparentToolbarStat = 0;
m_wndFloatToolBar->ShowWindow(SW_HIDE);
}


BOOL bThisIsAutoZoom = false; 自动大小


if(scale <= 0)
{
bThisIsAutoZoom = true;
scale =
s.iZoomLevel == 0 ? 0.5 :
s.iZoomLevel == 1 ? 1.0 :
s.iZoomLevel == 2 ? 2.0 :
s.iZoomLevel == 3 ? GetZoomAutoFitScale() :
1.0;


m_last_size_of_current_kind_of_video.cx = -1;
m_last_size_of_current_kind_of_video.cy = -1;
}


if(m_fFullScreen) 如果全屏 则全屏
{
OnViewFullscreen();
}


MINMAXINFO mmi;
OnGetMinMaxInfo(&mmi);


CRect r;
int w = 0, h = 0;


if(!m_fAudioOnly) 不是音频
{
CSize arxy = m_original_size_of_current_video = GetVideoSize();


long lWidth = int(arxy.cx * scale + 0.5);
long lHeight = int(arxy.cy * scale + 0.5);


CString string_remember_windows_size_for_this_video_size_parm;
string_remember_windows_size_for_this_video_size_parm.Format(L"ORGSIZE%dx%d", m_original_size_of_current_video.cx, m_original_size_of_current_video.cy );


AppSettings& s = AfxGetAppSettings();
long lPerfWidth = m_last_size_of_current_kind_of_video.cx = AfxGetMyApp()->GetProfileInt(ResStr(IDS_R_SETTINGS)+L"REMENBERWNDSIZE", string_remember_windows_size_for_this_video_size_parm+L"W", -1);
long lPerfHeight = m_last_size_of_current_kind_of_video.cy = AfxGetMyApp()->GetProfileInt(ResStr(IDS_R_SETTINGS)+L"REMENBERWNDSIZE", string_remember_windows_size_for_this_video_size_parm+L"H", -1);




DWORD style = GetStyle();


CRect r3 ,r4;
GetWindowRect(r3);
m_wndView.GetWindowRect(r4);
//GetClientRect(&r1);
//m_wndView.GetClientRect(&r2);
int wDelta = 0;
int hDelta = 0;


wDelta = r3.Width() - r4.Width();
hDelta = r3.Height() - r4.Height();


if(style&WS_CAPTION)
{
//h += GetSystemMetrics(SM_CYCAPTION);
//w += 2; h += 2; // for the 1 pixel wide sunken frame
//w += 2; h += 3; // for the inner black border
}


GetWindowRect(r);


if (lHeight + hDelta < 280 || lWidth + wDelta < 480) {
int w1 = 480 - wDelta;
int h1 = 280 - hDelta;
SVP_ASSERT(w1 > 0);
SVP_ASSERT(h1 > 0);


// Re-evaluate current 'w' and 'h' to keep aspect ratio
int h2 = arxy.cy * w1 / arxy.cx, w2 = arxy.cx * h1 / arxy.cy;
// Choose by the fitting rectangle.
if (h2 + hDelta >= 280) {
w = 480;
h = h2 + hDelta;
} else {
w = w2 + wDelta;
h = 280;
}


} else {
h = lHeight + hDelta;
w = lWidth + wDelta;
}


if(bThisIsAutoZoom && 0){
double mratio = (double)lHeight/lWidth;
//SVP_LogMsg5(L"%d %d %f %d %d %f",h , w, w * mratio + (h - lHeight), lHeight, lWidth, mratio);
h = max(h , w * mratio + (h - lHeight));
}


if(bThisIsAutoZoom && lPerfWidth > 240 && lPerfHeight > 120)
{
//Only do this if its auto zoom
w = lPerfWidth;
h = lPerfHeight;
}
}
else
{
GetWindowRect(r);


//w = r.Width(); //;mmi.ptMinTrackSize.x;
//h = r.Height();//;mmi.ptMinTrackSize.y;
w = 320;
if(s.bUserAeroUI()){
w /= 0.9;
}
h = 110;


AppSettings& s = AfxGetAppSettings();
long lPerfWidth = m_last_size_of_current_kind_of_video.cx = AfxGetMyApp()->GetProfileInt(ResStr(IDS_R_SETTINGS)+L"REMENBERWNDSIZE", L"ORGSIZE0x0W", -1);
long lPerfHeight = m_last_size_of_current_kind_of_video.cy = AfxGetMyApp()->GetProfileInt(ResStr(IDS_R_SETTINGS)+L"REMENBERWNDSIZE", L"ORGSIZE0x0H", -1);


w = max(w, lPerfWidth);
h = max(h, lPerfHeight);


}


// center window
//if(!s.fRememberWindowPos)
{
CPoint cp = r.CenterPoint();
r.left = cp.x - w/2;
r.top = cp.y - h/2;
}


r.right = r.left + w;
r.bottom = r.top + h;


MONITORINFO mi;
mi.cbSize = sizeof(MONITORINFO);


获得窗体信息
GetMonitorInfo(MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST), &mi);
if(r.right > mi.rcWork.right) r.OffsetRect(mi.rcWork.right-r.right, 0);
if(r.left < mi.rcWork.left) r.OffsetRect(mi.rcWork.left-r.left, 0);
if(r.bottom > mi.rcWork.bottom) r.OffsetRect(0, mi.rcWork.bottom-r.bottom);
if(r.top < mi.rcWork.top) r.OffsetRect(0, mi.rcWork.top-r.top);
CRect rcWork(mi.rcWork);
if(r.Width() > rcWork.Width() ){
r.left = rcWork.left;
r.right = rcWork.right;
}
if(r.Height() > rcWork.Height() ){
r.top = rcWork.top;
r.bottom = rcWork.bottom;
}
if(m_fFullScreen || !s.HasFixedWindowSize())
{
MoveWindow(r);
}


//AfxMessageBox(_T("1"));
//Sleep(200);
// ShowWindow(SW_SHOWNORMAL);


MoveVideoWindow();
}




进入CMainFrame::ToggleFullscreen 分析
void CMainFrame::ToggleFullscreen(bool fToNearest, bool fSwitchScreenResWhenHasTo)
{
CRect r;
m_lastTimeToggleFullsreen = AfxGetMyApp()->GetPerfCounter();
// const CWnd* pWndInsertAfter;
DWORD dwRemove = 0, dwAdd = 0;
DWORD dwRemoveEx = 0, dwAddEx = 0;
HMENU hMenu;


if(!m_fFullScreen)
{ 不是全屏


if(m_wndPlaylistBar.IsVisible()){
m_fPlaylistBeforeToggleFullScreen = true;
ShowControlBar(&m_wndPlaylistBar, FALSE, TRUE);
}


GetWindowRect(&m_lastWindowRect);


dispmode& dm = AfxGetAppSettings().dmFullscreenRes;
m_dmBeforeFullscreen.fValid = false;
if(dm.fValid && fSwitchScreenResWhenHasTo)
{
GetCurDispMode(m_dmBeforeFullscreen);
SetDispMode(dm);
}


MONITORINFO mi;
mi.cbSize = sizeof(MONITORINFO);
GetMonitorInfo(MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST), &mi);


dwRemove = WS_CAPTION|WS_THICKFRAME;
if(fToNearest) r = mi.rcMonitor;
else GetDesktopWindow()->GetWindowRect(&r);
hMenu = NULL;




}
else
{
全屏
if( AfxGetAppSettings().htpcmode){
return;
}
if( m_fPlaylistBeforeToggleFullScreen )
ShowControlBar(&m_wndPlaylistBar, TRUE, TRUE);


if(m_dmBeforeFullscreen.fValid)
SetDispMode(m_dmBeforeFullscreen);


dwAdd = (AfxGetAppSettings().fHideCaptionMenu ? 0 : WS_CAPTION) | WS_THICKFRAME;
r = m_lastWindowRect;
hMenu = NULL;//AfxGetAppSettings().fHideCaptionMenu ? NULL : m_hMenuDefault;
}






//bool fAudioOnly = m_fAudioOnly;
//m_fAudioOnly = true;


m_fFullScreen = !m_fFullScreen;


SetAlwaysOnTop(AfxGetAppSettings().iOnTop);


修改属性 进行全屏
ModifyStyle(dwRemove, dwAdd, SWP_NOZORDER);
ModifyStyleEx(dwRemoveEx, dwAddEx, SWP_NOZORDER);
::SetMenu(m_hWnd, hMenu);
SetWindowPos(NULL, r.left, r.top, r.Width(), r.Height(), SWP_NOZORDER|SWP_NOSENDCHANGING /*SWP_FRAMECHANGED*/);
RedrawNonClientArea();


KillTimer(TIMER_FULLSCREENCONTROLBARHIDER);
KillTimer(TIMER_FULLSCREENMOUSEHIDER);
if(m_fFullScreen)
{
// SVP_LogMsg5(L"Fullscreen");
m_fHideCursor = true;
SetTimer(TIMER_FULLSCREENMOUSEHIDER, 800, NULL);
ShowControls(CS_NONE, false);
}
else
{
m_lastMouseMove.x = m_lastMouseMove.y = -1;
m_fHideCursor = false;
ShowControls(AfxGetAppSettings().nCS);
}


m_wndView.SetWindowPos(NULL, 0, 0, 0, 0, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER);
//m_fAudioOnly = fAudioOnly;


rePosOSD();


MoveVideoWindow();


// insert after the HWND_TOP if the player is not full screen
if (m_fFullScreen) 全屏的话 就置顶
::SetWindowPos(m_hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOREDRAW|SWP_NOSIZE|SWP_NOMOVE);
else
::SetWindowPos(m_hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOREDRAW|SWP_NOSIZE|SWP_NOMOVE);
}




TIMER_STREAMPOSPOLLER: 定时事件
case TIMER_STREAMPOSPOLLER:
if (m_iMediaLoadState == MLS_LOADED)
_HandleTimer_StreamPosPoller();
break;


void CMainFrame::_HandleTimer_StreamPosPoller() 处理位置信息 比如播放进度
{
REFERENCE_TIME rtNow = 0, rtDur = 0;


if (m_iPlaybackMode == PM_FILE)
{
pMS->GetCurrentPosition(&rtNow);
pMS->GetDuration(&rtDur);


if (m_rtDurationOverride >= 0)
rtDur = m_rtDurationOverride;


m_wndSeekBar.Enable(rtDur > 0);
m_wndSeekBar.SetRange(0, rtDur);
m_wndSeekBar.SetPos(rtNow);
}
else if (m_iPlaybackMode == PM_CAPTURE)
{
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;


m_wndSeekBar.Enable(false);
m_wndSeekBar.SetRange(0, rtDur);
m_wndSeekBar.SetPos(rtNow);
/*
if (m_fCapturing)
{
if (rtNow > 10000i64*1000*60*60*3)
m_wndCaptureBar.m_capdlg.OnRecord();
}
*/
}


if (m_pCAP && (m_iPlaybackMode != PM_FILE || m_bMustUseExternalTimer))
{
g_bExternalSubtitleTime = true;
AfxGetAppSettings().bExternalSubtitleTime = true;
if (pDVDI)
{
DVD_PLAYBACK_LOCATION2 Location;
if (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;


LONGLONG rtTimeCode = HMSF2RT(Location.TimeCode, fps);
m_pCAP->SetTime(rtTimeCode);
}
else
m_pCAP->SetTime(/*rtNow*/m_wndSeekBar.GetPos());
}
else
m_pCAP->SetTime(/*rtNow*/m_wndSeekBar.GetPos());
}
else
{
g_bExternalSubtitleTime = false;
AfxGetAppSettings().bExternalSubtitleTime = false;
}
}




TIMER_STREAMPOSPOLLER2: 定时设置
case TIMER_STREAMPOSPOLLER2:
if (m_iMediaLoadState == MLS_LOADED) 设置位置 和 时间
{
__int64 start, stop, pos;
m_wndSeekBar.GetRange(start, stop);
pos = m_wndSeekBar.GetPosReal();


if (ABControlOn && m_bRefTime > m_aRefTime && GetMediaState() == State_Running)
{
if (pos > m_bRefTime)
//goto aRefTimer
SeekTo(m_aRefTime, 0);
}
GUID tf;
pMS->GetTimeFormat(&tf);


if (m_iPlaybackMode == PM_CAPTURE && !m_fCapturing)
{
CString str = _T("Live");
long lChannel = 0, lVivSub = 0, lAudSub = 0;
if (pAMTuner
&& m_wndCaptureBar.m_capdlg.IsTunerActive()
&& SUCCEEDED(pAMTuner->get_Channel(&lChannel, &lVivSub, &lAudSub)))
{
CString ch;
ch.Format(_T(" (ch%d)"), lChannel);
str += ch;
}
//m_wndStatusBar.SetStatusTimer(str);
m_wndToolBar.SetStatusTimer(str);
}
else
{
double pRate;
if (E_NOTIMPL == pMS->GetRate(&pRate))
pRate = 0;
m_wndToolBar.SetStatusTimer(pos, stop, 0, &tf, pRate);
//m_wndToolBar.SetStatusTimer(str);
}


if (m_pCAPR && GetMediaState() == State_Paused)
m_pCAPR->Paint(true);
}
break;








case TIMER_STATS: 定时 事件
_HandleTimer_Stats(); 处理事件状态
break;
void CMainFrame::_HandleTimer_Stats()
{
m_l_been_playing_sec++;
if (AfxGetMyApp()->IsWin7() && pTBL)
{
try
{
BOOL bHasValue = 0;
BOOL bSetPaused = 0;
if (IsSomethingLoaded()) 确认已经加载
{
//TBPF_PAUSED
//TBPF_NORMAL
//TBPF_INDETERMINATE
switch (GetMediaState())
{
case State_Paused:
//not using TBPF_PAUSED since it hide progress
pTBL->SetProgressState(m_hWnd,TBPF_NORMAL);
bSetPaused = true;
bHasValue = true;
break;
case State_Running:
pTBL->SetProgressState(m_hWnd,TBPF_NORMAL);
bHasValue = true;
break;
case State_Stopped:
pTBL->SetProgressState(m_hWnd,TBPF_NOPROGRESS);
break;
}
}
else
pTBL->SetProgressState(m_hWnd,TBPF_NOPROGRESS);


if (bHasValue)
{
__int64 iSeekStart, iSeekStop;
m_wndSeekBar.GetRange(iSeekStart, iSeekStop);
__int64 iSeekPos = m_wndSeekBar.GetPosReal();
pTBL->SetProgressValue(m_hWnd, iSeekPos ,(iSeekStop - iSeekStart));
}
if (bSetPaused)
pTBL->SetProgressState(m_hWnd,TBPF_PAUSED);
}
catch (...)
{
pTBL->Release();
pTBL = NULL;
}
}


if (IsSomethingLoaded() && m_fAudioOnly && (!m_Lyric.m_has_lyric || m_wndView.m_strAudioInfo.IsEmpty()))
{ 已经加载 是音频 没有歌词
m_wndView.m_AudioInfoCounter++;
BOOL bHaveInfo = false;


for (int i = 0; i < 4; i++)
{
if ((m_wndView.m_AudioInfoCounter%4) == 0 || m_wndView.m_strAudioInfo.IsEmpty())
{
CString szInfo , szMusicTitle, szMusicAuthor;
szMusicTitle = GetClipInfo(IDS_INFOBAR_TITLE).c_str();
szMusicAuthor = GetClipInfo(IDS_INFOBAR_AUTHOR).c_str();


switch (m_wndView.m_AudioInfoCounter/4 %4)
{
case 0:
szInfo = szMusicTitle;
break;
case 1:
szInfo = szMusicAuthor;
break;
case 2:
szInfo = GetClipInfo(IDS_INFOBAR_DESCRIPTION).c_str();
break;
case 3:
szInfo = GetClipInfo(IDS_INFOBAR_COPYRIGHT).c_str();
break;
}
if (szInfo.IsEmpty())
{
m_wndView.m_AudioInfoCounter+=4;
continue;
}
else
{
m_wndView.m_strAudioInfo = szInfo;
CString szTitleItShouleBe = szMusicTitle + _T(" - ") + szMusicAuthor;
if (szTitleItShouleBe != m_szTitle)
{
m_szTitle = szTitleItShouleBe;
RedrawNonClientArea();
}
m_wndView.Invalidate();
bHaveInfo = true;
}
}
break;
}
}


if (m_iPlaybackMode == PM_FILE)
{
REFERENCE_TIME rtNow = 0, rtDur = 0;
pMS->GetCurrentPosition(&rtNow);
pMS->GetDuration(&rtDur);




if (m_fAudioOnly && m_Lyric.m_has_lyric)// && m_wndLycShowBox
{
int iLastingTime;
CString szLyricLine = m_Lyric.GetCurrentLyricLineByTime(rtNow, &iLastingTime);
if (!szLyricLine.IsEmpty())
{
wchar_t music_note[] = {0x266A, 0x0020, 0};
szLyricLine.Insert(0, music_note);
if (m_wndView.m_strAudioInfo != szLyricLine)
{
m_wndView.m_strAudioInfo = szLyricLine;
if (iLastingTime > 0)
m_wndView.SetLyricLasting(iLastingTime);
else
m_wndView.SetLyricLasting(15);
m_wndView.Invalidate();
}
}
}


UINT iTotalLenSec = (UINT)( (INT64) rtDur / 20000000 );
//如果视频长度大于1分钟, 而且是文件模式,而且正在播放中
if (!m_fAudioOnly && iTotalLenSec > 180 && m_iPlaybackMode == PM_FILE && GetMediaState() == State_Running)
{
time_t time_now = time(NULL);
UINT totalplayedtime = time_now - m_tPlayStartTime;
//SVP_LogMsg5(L"time_now > ( m_tLastLogTick %f %f" , (double)time_now , (double)m_tLastLogTick);
if (time_now > ( m_tLastLogTick + 180 ))
{ //如果和上次检查已经超n秒
CString fnVideoFile , fnSubtitleFile;
int subDelayMS = 0;
fnVideoFile = m_fnCurPlayingFile;
fnSubtitleFile = getCurPlayingSubfile(&subDelayMS);


if (!fnSubtitleFile.IsEmpty())
{ //如果有字幕
CString szLog;
//szLog.Format(_T(" %s ( with sub %s delay %d ) %d sec of %d sec ( 1/2 length video = %d ) ") , fnVideoFile, fnSubtitleFile,subDelayMS, totalplayedtime , iTotalLenSec, (UINT)(iTotalLenSec/2) );
//SVP_LogMsg(szLog);
//if time > 50%
if (totalplayedtime > (UINT)(iTotalLenSec/2))
{
if (!m_haveSubVoted && m_pCAP && rtNow > (rtDur - 3000000000i64))
{
//如果还没提示过vote
//如果时间接近最末5分钟
AppSettings& s = AfxGetAppSettings();
if (s.bIsChineseUIUser())
{
//如果是中文
if ( m_wndPlaylistBar.GetCount() <= 1)
{
//如果是1CD
int nSubPics;
REFERENCE_TIME rtSubNow, rtSubStart, rtSubStop;
m_pCAP->GetSubStats(nSubPics,rtSubNow, rtSubStart, rtSubStop);
if (rtSubNow > rtSubStop)
{
//如果没有更多字幕
SVP_LogMsg5(L"Sub Voted Event");
//vote之
m_haveSubVoted = true;
}
}
}
}
//是否已经上传过呢
if (m_fnsAlreadyUploadedSubfile.Find(fnVideoFile+fnSubtitleFile) < 0)
{
//upload subtitle
Logging(L"Uploading sub %s of %s width delay %d ms since user played %d sec of %d sec ( more than 1/2 length video ) " , fnSubtitleFile, fnVideoFile ,subDelayMS, totalplayedtime , iTotalLenSec );
SVP_UploadSubFileByVideoAndSubFilePath(fnVideoFile , fnSubtitleFile, subDelayMS);
m_fnsAlreadyUploadedSubfile.Append( fnVideoFile+fnSubtitleFile+_T(";") );
}
int subDelayMS2 = 0;
CString fnSubtitleFile2 = getCurPlayingSubfile(&subDelayMS2);
if (!fnSubtitleFile2.IsEmpty())
{
if (m_fnsAlreadyUploadedSubfile.Find( fnVideoFile+fnSubtitleFile2 ) < 0)
{
//upload subtitle
Logging((L"Uploading sub2 %s of %s width delay %d ms since user played %d sec of %d sec ( more than 1/2 length video ) ") , fnSubtitleFile2, fnVideoFile ,subDelayMS2, totalplayedtime , iTotalLenSec);
SVP_UploadSubFileByVideoAndSubFilePath(fnVideoFile , fnSubtitleFile2, subDelayMS2);
m_fnsAlreadyUploadedSubfile.Append( fnVideoFile+fnSubtitleFile2+_T(";") );
}
}
}
}
m_tLastLogTick = time_now;
//SVP_LogMsg5(L"m_tLastLogTick = time_now; %f %f" , (double)time_now , (double)m_tLastLogTick);
}
}
}


CString msg;
if (m_fBuffering)
{
BeginEnumFilters(pGB, pEF, pBF)
{
if (CComQIPtr<IAMNetworkStatus, &IID_IAMNetworkStatus> pAMNS = pBF)
{
long BufferingProgress = 0;
if (SUCCEEDED(pAMNS->get_BufferingProgress(&BufferingProgress)) && BufferingProgress > 0 && BufferingProgress < 99)
{
msg.Format(ResStr(IDS_CONTROLS_BUFFERING), BufferingProgress);
SendStatusMessage(msg,1000);
SVP_LogMsg5(msg);
}
break;
}
}
EndEnumFilters
}
else if (pAMOP)
{
__int64 t = 0, c = 0;
if(SUCCEEDED(pAMOP->QueryProgress(&t, &c)) && t > 0 && c < t)
{
msg.Format(ResStr(IDS_CONTROLS_BUFFERING), c*100/t);
SendStatusMessage(msg,1000);
SVP_LogMsg5(msg);
}
}
m_wndToolBar.m_buffering = msg;


if (m_iPlaybackMode == PM_FILE)
SetupChapters();



if (GetMediaState() == State_Running)
{
if (m_fAudioOnly)
{
UINT fSaverActive = 0;
if (SystemParametersInfo(SPI_GETPOWEROFFACTIVE, 0, (PVOID)&fSaverActive, 0))
{
SystemParametersInfo(SPI_SETPOWEROFFACTIVE, 0, 0, SPIF_SENDWININICHANGE); // this might not be needed at all...
SystemParametersInfo(SPI_SETPOWEROFFACTIVE, fSaverActive, 0, SPIF_SENDWININICHANGE);
}
SetThreadExecutionState(ES_SYSTEM_REQUIRED);
}
else
{
UINT fSaverActive = 0;
if (SystemParametersInfo(SPI_GETSCREENSAVEACTIVE, 0, (PVOID)&fSaverActive, 0))
{
SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, 0, 0, SPIF_SENDWININICHANGE); // this might not be needed at all...
SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, fSaverActive, 0, SPIF_SENDWININICHANGE);
}
fSaverActive = 0;
if (SystemParametersInfo(SPI_GETPOWEROFFACTIVE, 0, (PVOID)&fSaverActive, 0))
{
SystemParametersInfo(SPI_SETPOWEROFFACTIVE, 0, 0, SPIF_SENDWININICHANGE); // this might not be needed at all...
SystemParametersInfo(SPI_SETPOWEROFFACTIVE, fSaverActive, 0, SPIF_SENDWININICHANGE);
}
SetThreadExecutionState(ES_DISPLAY_REQUIRED|ES_SYSTEM_REQUIRED); //this is the right way, only this work under vista . no ES_CONTINUOUS so it can goes to sleep when not playing
}




if (GetExStyle() & WS_EX_LAYERED)
{
BYTE dAlpha = 0 ;
DWORD dwFlag = 0;
if (AfxGetMyApp()->m_pGetLayeredWindowAttributes)
{
AfxGetMyApp()->m_pGetLayeredWindowAttributes(m_hWnd, NULL, &dAlpha , &dwFlag);
if (dAlpha == 255)
ModifyStyleEx(WS_EX_LAYERED , 0);
}
}

}


namespace DSObjects 操作DirectShow类库


空间中有
操作DirectShow D3D7
CDX7AllocatorPresenter继承ISubPicAllocatorPresenterImpl


操作DirectShow D3D9
CDX9AllocatorPresenter继承ISubPicAllocatorPresenterImpl


CDXRAllocatorPresenter继承ISubPicAllocatorPresenterImpl


VMR7分配器
CVMR7AllocatorPresenter继承CDX7AllocatorPresenter,继承IVMRSurfaceAllocator,继承IVMRImagePresenter,继承IVMRWindowlessControl


VMR9分配器
CVMR9AllocatorPresenter继承CDX9AllocatorPresenter,继承IVMRSurfaceAllocator9,继承IVMRImagePresenter9, 继承IVMRWindowlessControl9


CGenlock 管理视频和显示的同步。


VR分配器
CmadVRAllocatorPresenter继承ISubPicAllocatorPresenterImpl


QT7分配器
CQT7AllocatorPresenter继承CDX7AllocatorPresenter,继承IQTVideoSurface


QT9分配器
CQT9AllocatorPresenter继承CDX9AllocatorPresenter,继承IQTVideoSurface


Quicktime格式绘图
CQuicktimeGraph继承CBaseGraph,继承IVideoFrameStep


Quicktime载体
CQuicktimeWindow继承CPlayerWindow


Real格式绘图
CRealMediaGraph继承CBaseGraph


Real格式播放
CRealMediaPlayer继承CUnknown,继承IRMAErrorSink,继承IRMAClientAdviseSink,继承IRMAAuthenticationManager,继承IRMASiteSupplier,继承IRMAPassiveSiteWatcher,继承IRMAAudioHook


Real格式播放载体
CRealMediaPlayerWindowed继承CRealMediaPlayer


Real格式播放载体
CRealMediaPlayerWindowless继承CRealMediaPlayer


Real格式视频面
CRealMediaVideoSurface继承CUnknown,继承IRMAVideoSurface


Real格式载体站点
CRealMediaWindowlessSite继承CUnknown,继承IRMASite,继承IRMASite2,继承IRMASiteWindowless,继承IRMAVideoSurface


RM7分配器
CRM7AllocatorPresenter继承CDX7AllocatorPresenter,继承IRMAVideoSurface


RM9分配器
CRM9AllocatorPresenter继承CDX9AllocatorPresenter,继承IRMAVideoSurface


Flash绘图
CShockwaveGraph继承CBaseGraph






主程序有的类库:


链接广告的类 实现了动画效果
AdController继承ThreadHelperImpl<AdController>


ButtonManage 按钮管理类


CAboutDlg继承CDialog 关于对话框


自定义了一个映射模版类
template <class T = CString, class S = CString>
class CAtlStringMap : public CAtlMap<S, T, CStringElementTraits<S> > {};


一个音频格式集合类
class CAudFormatArray : public CFormatArray<AUDIO_STREAM_CONFIG_CAPS>


一个作者登陆框
class CAuthDlg : public CDialog


视频绘画类
class CBaseGraph继承CUnknown, 继承IGraphBuilder2, public IMediaControl, 继承IMediaEventEx, 继承IMediaSeeking, 继承IVideoWindow, 继承IBasicVideo, 继承IBasicAudio, 继承IAMOpenProgress, public IGraphEngine




class CBtnAlign 按钮位置区域对齐类


自绘了Edit类 阙套了Button
class CBtnEditCtrl继承CWindowImpl<CBtnEditCtrl, CEdit>


CChildView继承CWnd 窗体类 实现了视频载体


COM组件属性页站点
CComPropertyPageSite继承CUnknown,继承IPropertyPageSite


CConvertChapDlg继承CResizableDialog 转换章节对话框


CConvertDlg继承CResizableDialog 转换对话框


CConvertPropsDlg继承CResizableDialog 转换属性页对话框


CConvertResDlg继承CResizableDialog 转换资源对话框


分行过滤器
CDeinterlacerFilter继承CTransformFilter


CDisplaySettingDetector 显示设置探测器


CDlgChkUpdater继承CDialog 确认更新对话框


CDropTarget 移动文件类


EVR分配器
CEVRAllocatorPresenter继承CDX9AllocatorPresenter,继承IMFGetService,继承IMFTopologyServiceLookupClient,继承IMFVideoDeviceID,继承IMFVideoPresenter,继承IDirect3DDeviceManager9,继承IMFAsyncCallback,继承IQualProp,继承IMFRateSupport,继承IMFVideoDisplayControl,继承IEVRTrustedVideoPlugin


渐变视频解码
CFakeDirectXVideoDecoder继承CUnknown,继承IDirectXVideoDecoder


CFavoriteAddDlg继承CCmdUIDialog 收藏对话框


CFavoriteOrganizeDlg继承CResizableDialog 收藏组织对话框


CFFindByDir 目录查找类


CFFindMoreFiles 查找更多文件类


CFGAggregator继承CUnknown FG集合类


CFGFilter FG过滤类


CFGFilterFile继承CFGFilter FG过滤文件


CFGFilterInternal继承CFGFilter FG内部过滤


CFGFilterList FG过滤列表


CFGFilterRegistry继承CFGFilter FG过滤继承类


CFGFilterVideoRenderer继承CFGFilter FG过滤视频渲染类


FG管理类
CFGManager继承CUnknown, 继承IGraphBuilder2, 继承IGraphBuilderDeadEnd, 继承CCritSec


CFGManagerCapture继承CFGManagerPlayer FG捕捉管理类


CFGManagerCustom继承CFGManager FG自定义管理类


CFGManagerDVD继承CFGManagerPlayer FG_DVD管理类


CFGManagerMuxer继承CFGManagerCustom FG 混合器管理类


CFGManagerPlayer继承CFGManagerCustom FG视频管理


CFileDropTarget继承COleDropTarget 文件移动类


CFilterMapper2继承CUnknown继承IFilterMapper2 过滤映射类


CFilterTreeCtrl继承CTreeCtrl 过滤器树列表


CFloatEdit继承CEdit 浮动的编辑框


格式模块
template<class T>
class CFormat : public CAutoPtrArray<CFormatElem<T> >


格式数组模块
template<class T>
class CFormatArray : public CAutoPtrArray<CFormat<T> >


格式节点
template<class T>
class CFormatElem


CGoToDlg继承CDialog 转到对话框


CGraphCore / /我们需要打开/播放暂停/寻求/关闭/ VOL控制/子控制/音频和视频切换的类


CGraphThread继承CWinThread 播放线程类


CHexEdit继承CEdit 16进制编辑框


ChkDefPlayerControlBar继承 CSVPDialog 默认播放控制航


CIfo 文件信息类


CInfoReport继承CDialog 信息报告对话框


CInPlaceComboBox继承CComboBox 阙套下拉框


CInPlaceEdit继承CEdit 阙套编辑框


CInPlaceListBox继承CListBox 阙套列表框


CIntEdit继承CEdit 整形编辑框


CKeyProvider继承CUnknown,继承IServiceProvider 键盘提供者


CLineNumberEdit继承CEdit 线数编辑框


CLineNumberStatic继承CStatic 线数静态框




CMacrovisionKicker继承CUnknown,继承IKsPropertySet


主程序
CMainFrame继承CFrameWnd,继承CDropTarget,继承CGraphCore




CMediaFormatCategory 媒体格式分类


CMediaTypesDlg继承CResizableDialog 媒体类型对话框


CMemoryDC继承CDC 内存离屏DC


CMPlayerCApp继承CWinApp 启动类


CNEWOSDWnd继承CWnd Osd窗体


ContentTypeTemp 内容类型


COpenCapDeviceDlg继承CResizableDialog 打开捕捉设备对话框


COpenDlg继承CResizableDialog 打开对话框


COpenFileDlg继承CFileDialog 打开文件对话框


COpenURLDlg继承CResizableDialog 打开URL 对话框


输出EVR
COuterEVR继承CUnknown,继承IVMRffdshow9,继承IVMRMixerBitmap9,继承IBaseFilter


输出VMR9
COuterVMR9继承CUnknown,继承IVideoWindow, 继承IBasicVideo2,继承IVMRWindowlessControl,继承IVMRffdshow9,继承IVMRMixerBitmap9


CPixelShaderCompiler 像素着色器编译器


CPlayerCaptureBar继承baseCPlayerCaptureBar 视频捕捉条


CPlayerCaptureDialog继承CResizableDialog //CDialog 视频捕捉对话框


CPlayerChannelNormalizer继承CSVPDialog 视频通道正规化对话框


CPlayerColorControlBar继承CSVPDialog 视频颜色控制条


CPlayerEQControlBar继承CSVPDialog 视频EQ控制条


CPlayerFloatToolBar继承CFrameWnd 视频浮动控制条


CPlayerListCtrl继承CListCtrl 播放器列表


CPlayerPlaylistBar继承CSizingControlBarG 播放器列表条


CPlayerSeekBar继承CDialogBar 视频跳转条


CPlayerShaderEditorBar继承baseCPlayerShaderEditorBar 视频着色编辑条


CPlayerToolBar继承CToolBar 视频工具条


CPlayerToolTopBar继承CWnd 视频上面的工具条


CPlayerWindow继承 CWnd 视频窗体


CPlaylist继承CList<CPlaylistItem> 播放列表


CPlaylistItem 播放列表节点


CPngImage继承CImage 处理png图片


CPnSPresetsDlg继承CCmdUIDialog 预设对话框


CPPageBase继承CCmdUIPropertyPage 基本属性页


CPPageFileInfoClip继承CPropertyPage 文件信息属性页


CPPageFileInfoDetails继承CPropertyPage 详细文件信息页


CPPageFileInfoRes继承CPPageBase 文件信息资源属性页


CPPageFileInfoSheet继承CPropertySheet 文件信息页


CPPageFileMediaInfo继承CPropertyPage 媒体文件信息


CPPageFormats 页格式


CResetDVD继承CDVDSession 重设DVD


CSaveDlg继承CCmdUIDialog 保存对话框


CSaveTextFileDialog继承CFileDialog 保存文本文件对话框


CSaveThumbnailsDialog继承CFileDialog 保存缩略图对话框


CSeekBarTip继承CWnd 赚到提示信息


CShaderAutoCompleteDlg继承CResizableDialog 着色自动完成对话框


CShaderCombineDlg继承CResizableDialog 着色连接对话框


CShaderEdit继承CLineNumberEdit 着色编辑框


CShaderEditorDlg继承CResizableDialog 着色编辑对话框


CShaderLabelComboBox继承CComboBox 着色下拉框


CShockwaveFlash继承CWnd flash控件


CSUIBtnList继承CList<CSUIButton*> 按钮列表


CSUIButton 自绘按钮类


CSVPButton继承CButton 自绘按钮


CSVPDialog继承CWnd 自绘对话框


CSVPSliderCtrl继承CSliderCtrl 自绘Slider


CSVPStatic继承CStatic 自绘Static


CSVPSubUploadDl继承CResizableDialog 字幕上传对话框


CSVPSubVoteControlBar继承CSVPDialog


CTextFile继承CStdioFile 操作文件类


CTextPassThruFilter继承CBaseFilter,继承CCritSec 文本直通过滤器


CTextPassThruInputPin继承CSubtitleInputPin 文本直通输入流


CTextPassThruOutputPin继承CBaseOutputPin 文本直通输出流


CTransparentControlBar继承CSVPDialog 透明控制条


CustomDrawBtn继承CButton 自定义按钮


CVidFormatArray继承CFormatArray<VIDEO_STREAM_CONFIG_CAPS> 视频格式集合


CVolumeCtrl继承CSliderCtrl 声音控件


CWebTextFile继承CTextFile 网站文本


FileAssoc 文件关联


FilterOverride 过滤器重叠


FrameCfgFileManage 窗体设置文件管理


GUIConfigManage GUI配置管理


哈希值管理
HashController继承LazyInstanceImpl<HashController>


HotkeyCmd继承ACCEL 快捷键


HotkeyController继承LazyInstanceImpl<HotkeyController> 快捷键控制


HotkeySchemeParser 快捷键计划分析器


LayeredWindowUtils 窗体单元


实例模版
template<class T>
class LazyInstanceImpl


template<class T>
class MainFrameSPlayerCmd


MakeMultiplyBmp


媒体中心管理
MediaCenterController继承LazyInstanceImpl<MediaCenterController>


媒体中心视图
MediaCenterView继承ATL::CWindowImpl<MediaCenterView>,继承MediaScrollbar,继承MediaListView


MediaCheckDB继承ThreadHelperImpl<MediaCheckDB> 媒体确认数据库


MediaDB 媒体数据库


MediaListView 媒体列表视图


MediaModel继承SourceModel<MediaData, MediaFindCondition> 媒体模式


MediaScrollbar 媒体滚动条


MediaSpiderAbstract继承ThreadHelperImpl<T> 媒体摘要


MediaSpiderFolderTree继承MediaSpiderAbstract<MediaSpiderFolderTree> 媒体摘要树


MediaSQLite 媒体SQL


MediaTreeModel 媒体树模式


MovieComment继承CDHtmlDialog 电影评论


NetworkControlerImpl 网络任务控制接口


OpenDeviceData继承OpenMediaData 设备打开方式


OpenDVDData继承OpenMediaData DVD打开方式


OpenFileData继承OpenMediaData 文件打开方式


OpenMediaData 打开方式基类


建议选项属性页
OptionAdvancedPage继承WTL::CPropertyPageImpl<OptionAdvancedPage>,继承WTL::CWinDataExchange<OptionAdvancedPage>


关联文件属性页
OptionAssociationPage继承WTL::CPropertyPageImpl<OptionAssociationPage>,继承WTL::CWinDataExchange<OptionAssociationPage>


基本选项属性页
OptionBasicPage继承WTL::CPropertyPageImpl<OptionBasicPage>,继承WTL::CWinDataExchange<OptionBasicPage>


OptionDlg继承WTL::CPropertySheetImpl<OptionDlg> 选项对话框


第二字幕选项属性页
OptionSubtitlePage继承WTL::CPropertyPageImpl<OptionSubtitlePage>,继承WTL::COwnerDraw<OptionSubtitlePage>,继承WTL::CWinDataExchange<OptionSubtitlePage>


OSDController继承LazyInstanceImpl<OSDController> OSD控制


OSDView继承ATL::CWindowImpl<OSDView>,继承LayeredWindowUtils<OSDView> OSD视图


PlayerPreference继承LazyInstanceImpl<PlayerPreference> 播放器引用


PlaylistController继承LazyInstanceImpl<PlaylistController> 播放列表控制


PlaylistParser 播放列表分析


播放列表视图
PlaylistView继承ATL::CWindowImpl<PlaylistView>,继承WTL::COwnerDraw<PlaylistView>,继承 WTL::CCustomDraw<PlaylistView>


PlaylistViewMfcProxy继承CSizingControlBarG 播放列表代理


SkinDownload继承CDHtmlDialog,继承ThreadHelperImpl<SkinDownload> 皮肤下载


SkinFolderManager 皮肤管理类


SnapUploadController继承ThreadHelperImpl<SnapUploadController> 对齐上传控制器


源模式模块
template<class TDATA, class TCONDITION>
class SourceModel


SPlayerGUID 播放ID


SQLliteapp 操作数据库


ssftest 测试ssf


SubtitleStyle 内部风格指数提供了实际的映射 字幕渲染设置接受外部字幕滤镜。它还提供Windows基于GDI画画的能力
模拟渲染对话框显示的目的。


字幕透明控制
SubTransController继承ThreadHelperImpl<SubTransController>,继承NetworkControlerImpl


SubTransFormat 字幕透明格式


SUIVoteStar


SVPLycShowBox //歌词显示面板 mouseover时显示半透明玻璃背景、关闭按钮和变色按钮,out后仅显示文字
//默认在屏幕底部区域显示,可以通过拖拽改变位置 关闭后改为在主窗口界面内显示


ThemePkg 主题背景


ThemePkgController 主题背景控制


TimeBmpManage 事件画面控制


上传控制
UbdUploadController继承ThreadHelperImpl<UbdUploadController>,继承LazyInstanceImpl<UbdUploadController>


UnCompressZip 解压控制


更新控制
UpdateController继承NetworkControlerImpl,继承ThreadHelperImpl<UpdateController>,继承LazyInstanceImpl<UpdateController>


用户着色控制
UserShareController继承NetworkControlerImpl,继承ThreadHelperImpl<UserShareController>,继承LazyInstanceImpl<UserShareController>


用户行为控制
UsrBehaviorController继承LazyInstanceImpl<UsrBehaviorController>


用户行为数据
UsrBehaviorData



今天主要针对 SPlayer 播放器项目的 CMPlayerc 分析

mplayerc

-->Model\appSQLite.h 主要负责操作sql
类成员成员中有两个成员
SQLliteapp* sqlite_setting;
SQLliteapp* sqlite_local_record;

对sqlite_setting 分析

在StoreSettingsToIni 产生一个对象
sqlite_setting = PlayerPreference::GetInstance()->GetSqliteSettingPtr();


保存数据前 存在 则开始输出 BEGIN
if(pApp->sqlite_setting){
pApp->sqlite_setting->begin_transaction();
}
保存数据后 存在 则开始输出 END
if(pApp->sqlite_setting){
pApp->sqlite_setting->end_transaction();
}

读取整形数据
if(sqlite_setting){
return sqlite_setting->GetProfileInt( lpszSection, lpszEntry, nDefault);
}else{
return __super::GetProfileInt( lpszSection, lpszEntry, nDefault);
}
}

写入整形数据
if(sqlite_setting){
return sqlite_setting->WriteProfileInt( lpszSection, lpszEntry, nValue);
}else{
SVP_LogMsg6("dwqdwq");
return __super::WriteProfileInt( lpszSection, lpszEntry, nValue);
}

读取字符集数据
if(sqlite_setting){
return sqlite_setting->GetProfileString( lpszSection, lpszEntry,
lpszDefault );
}else{
return __super::GetProfileString( lpszSection, lpszEntry,
lpszDefault );
}


写入字符集数据
if(sqlite_setting){
return sqlite_setting->WriteProfileString( lpszSection, lpszEntry,
lpszValue);
}else{
return __super::WriteProfileString( lpszSection, lpszEntry,
lpszValue);
}


读取二进制数据
if(sqlite_setting){
return sqlite_setting->GetProfileBinary( lpszSection, lpszEntry,
ppData, pBytes);
}else{
return __super::GetProfileBinary( lpszSection, lpszEntry,
ppData, pBytes);
}


写入二进制数据
if(sqlite_setting){
return sqlite_setting->WriteProfileBinary( lpszSection, lpszEntry,
pData, nBytes);
}else{
return __super::WriteProfileBinary( lpszSection, lpszEntry,
pData, nBytes);
}


对sqlite_setting 分析完
对sqlite_local_record 分析
在InitInstanceThreaded(INT64 CLS64) 函数中 产生对象


sqlite_local_record = new SQLliteapp(tmPath.m_strPath.GetBuffer())

判断是否打开数据库
if(!sqlite_local_record->db_open)
{
delete sqlite_local_record;
sqlite_local_record = NULL;
}

执行数据库 主要是创建表
if(sqlite_local_record)
{
sqlite_local_record->exec_sql(L"CREATE TABLE IF NOT EXISTS histories_stream (\"fpath\" TEXT, \"subid\" INTEGER, \"subid2\" INTEGER, \"audioid\" INTEGER, \"videoid\" INTEGER )");
sqlite_local_record->exec_sql(L"CREATE UNIQUE INDEX IF NOT EXISTS \"hispks\" on histories_stream (fpath ASC)");


sqlite_local_record->exec_sql(L"CREATE TABLE IF NOT EXISTS histories (\"fpath\" TEXT, \"subid\" INTEGER, \"subid2\" INTEGER, \"audioid\" INTEGER, \"stoptime\" INTEGER, \"modtime\" INTEGER )");
sqlite_local_record->exec_sql(L"CREATE UNIQUE INDEX IF NOT EXISTS \"hispk\" on histories (fpath ASC)");
sqlite_local_record->exec_sql(L"CREATE INDEX IF NOT EXISTS \"modtime\" on histories (modtime ASC)");


sqlite_local_record->exec_sql(L"CREATE TABLE IF NOT EXISTS settingstring (\"hkey\" TEXT, \"sect\" TEXT, \"vstring\" TEXT )");
sqlite_local_record->exec_sql(L"PRAGMA synchronous=OFF");
//sqlite_local_record->end_transaction();
}

在退出程序的时候 ExitInstance()
if(sqlite_local_record){
CString szSQL;
szSQL.Format(L"DELETE FROM histories WHERE modtime < '%d' ", time(NULL)-3600*24*30);
// SVP_LogMsg5(szSQL);
sqlite_local_record->exec_sql(szSQL.GetBuffer());
sqlite_local_record->exec_sql(L"PRAGMA synchronous=ON");
}
if (sqlite_local_record) delete sqlite_local_record;
$(ConfigurationName)


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics