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

多媒体编程

开发平台:

Visual C++

  1. /* 
  2.  * Copyright (C) 2003-2006 Gabest
  3.  * http://www.gabest.org
  4.  *
  5.  *  This Program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2, or (at your option)
  8.  *  any later version.
  9.  *   
  10.  *  This Program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13.  *  GNU General Public License for more details.
  14.  *   
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with GNU Make; see the file COPYING.  If not, write to
  17.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  18.  *  http://www.gnu.org/copyleft/gpl.html
  19.  *
  20.  */
  21. #include "stdafx.h"
  22. #include "mplayerc.h"
  23. #include <math.h>
  24. #include <atlbase.h>
  25. #include <atlcoll.h>
  26. #include <initguid.h>
  27. #include "RealMediaGraph.h"
  28. #include "RealMediaWindowlessSite.h"
  29. #include "......includeRealMediarmavsurf.h"
  30. #include "......includeRealMediarmaevent.h"
  31. #include "......includeRealMediarmaprefs.h"
  32. #include "....DSUtilDSUtil.h"
  33. #include "AuthDlg.h"
  34. // CRealMediaPlayer
  35. CRealMediaPlayer::CRealMediaPlayer(HWND hWndParent, CRealMediaGraph* pRMG) 
  36. : CUnknown(NAME("CRealMediaPlayer"), NULL)
  37. , m_pRMG(pRMG)
  38. , m_hWndParent(hWndParent)
  39. , m_fpCreateEngine(NULL), m_fpCloseEngine(NULL), m_hRealMediaCore(NULL)
  40. , m_State(State_Stopped), m_UserState(State_Stopped), m_nCurrent(0), m_nDuration(0)
  41. , m_VideoSize(0, 0)
  42. , m_fVideoSizeChanged(true)
  43. {
  44. }
  45. CRealMediaPlayer::~CRealMediaPlayer()
  46. {
  47. Deinit();
  48. }
  49. bool CRealMediaPlayer::Init()
  50. {
  51. CString prefs(_T("Software\RealNetworks\Preferences"));
  52. CRegKey key;
  53. if(ERROR_SUCCESS != key.Open(HKEY_CLASSES_ROOT, prefs + _T("\DT_Common"), KEY_READ))
  54. return(false);
  55. TCHAR buff[MAX_PATH];
  56. ULONG len = sizeof(buff);
  57. if(ERROR_SUCCESS != key.QueryStringValue(NULL, buff, &len))
  58. return(false);
  59. key.Close();
  60. if(!(m_hRealMediaCore = LoadLibrary(CString(buff) + _T("pnen3260.dll")))) 
  61. return(false);
  62. m_fpCreateEngine = (FPRMCREATEENGINE)GetProcAddress(m_hRealMediaCore, "CreateEngine");
  63. m_fpCloseEngine = (FPRMCLOSEENGINE)GetProcAddress(m_hRealMediaCore, "CloseEngine");
  64. m_fpSetDLLAccessPath = (FPRMSETDLLACCESSPATH)GetProcAddress(m_hRealMediaCore, "SetDLLAccessPath");
  65. if(!m_fpCreateEngine || !m_fpCloseEngine || !m_fpSetDLLAccessPath)
  66. return(false);
  67. if(ERROR_SUCCESS == key.Open(HKEY_CLASSES_ROOT, prefs, KEY_READ))
  68. {
  69. CString dllpaths;
  70. len = sizeof(buff);
  71. for(int i = 0; ERROR_SUCCESS == key.EnumKey(i, buff, &len); i++, len = sizeof(buff))
  72. {
  73. CRegKey key2;
  74. TCHAR buff2[MAX_PATH];
  75. ULONG len2 = sizeof(buff2);
  76. if(ERROR_SUCCESS != key2.Open(HKEY_CLASSES_ROOT, prefs + _T("\") + buff, KEY_READ)
  77. || ERROR_SUCCESS != key2.QueryStringValue(NULL, buff2, &len2))
  78. continue;
  79. dllpaths += CString(buff) + '=' + buff2 + '|';
  80. }
  81. key.Close();
  82. if(!dllpaths.IsEmpty())
  83. {
  84. char* s = new char[dllpaths.GetLength()+1];
  85. strcpy(s, CStringA(dllpaths));
  86. for(int i = 0, j = strlen(s); i < j; i++) {if(s[i] == '|') s[i] = '';}
  87. m_fpSetDLLAccessPath(s);
  88. delete [] s;
  89. }
  90. }
  91. if(PNR_OK != m_fpCreateEngine(&m_pEngine))
  92. return(false);
  93. if(PNR_OK != m_pEngine->CreatePlayer(*&m_pPlayer))
  94. return(false);
  95. if(!(m_pSiteManager = m_pPlayer) || !(m_pCommonClassFactory = m_pPlayer))
  96. return(false);
  97. m_pAudioPlayer = m_pPlayer;
  98. m_pAudioPlayer->AddPostMixHook(static_cast<IRMAAudioHook*>(this), FALSE, FALSE);
  99. // m_pVolume = m_pAudioPlayer->GetDeviceVolume();
  100. m_pVolume = m_pAudioPlayer->GetAudioVolume();
  101. // IRMAVolume::SetVolume has a huge latency when used via GetAudioVolume,
  102. // but by lowering this audio pushdown thing it can get better
  103. CComQIPtr<IRMAAudioPushdown, &IID_IRMAAudioPushdown> pAP = m_pAudioPlayer;
  104. if(pAP) pAP->SetAudioPushdown(300); // 100ms makes the playback sound choppy, 200ms looks ok, but for safety we set this to 300ms... :P
  105. CComQIPtr<IRMAErrorSinkControl, &IID_IRMAErrorSinkControl> pErrorSinkControl = m_pPlayer;
  106. if(pErrorSinkControl) pErrorSinkControl->AddErrorSink(static_cast<IRMAErrorSink*>(this), PNLOG_EMERG, PNLOG_INFO);
  107. if(PNR_OK != m_pPlayer->AddAdviseSink(static_cast<IRMAClientAdviseSink*>(this)))
  108. return(false);
  109. if(PNR_OK != m_pPlayer->SetClientContext((IUnknown*)(INonDelegatingUnknown*)(this)))
  110. return(false);
  111. // TODO
  112. /*
  113. if(CComQIPtr<IRMAPreferences, &IID_IRMAPreferences> pPrefs = m_pPlayer)
  114. {
  115. CComPtr<IRMABuffer> pBuffer;
  116. HRESULT hr = pPrefs->ReadPref("HTTPProxyHost", *&pBuffer);
  117. UCHAR* pData = NULL;
  118. ULONG32 ulLength = 0;
  119. hr = pBuffer->Get(pData, ulLength);
  120. pBuffer = NULL;
  121. hr = m_pCommonClassFactory->CreateInstance(CLSID_IRMABuffer, (void**)&pBuffer);
  122. hr = pBuffer->SetSize(strlen("localhost")+1);
  123. pData = pBuffer->GetBuffer();
  124. strcpy((char*)pData, "localhost");
  125. hr = pBuffer->Set(pData, strlen("localhost")+1);
  126. pData = NULL;
  127. ulLength = 0;
  128. hr = pBuffer->Get(pData, ulLength);
  129. hr = pPrefs->WritePref("HTTPProxyHost", pBuffer);
  130. hr = hr;
  131. }
  132. */
  133. return(true);
  134. }
  135. void CRealMediaPlayer::Deinit()
  136. {
  137. if(m_pPlayer)
  138. {
  139. m_pPlayer->Stop();
  140. CComQIPtr<IRMAErrorSinkControl, &IID_IRMAErrorSinkControl> pErrorSinkControl = m_pPlayer;
  141. if(pErrorSinkControl) pErrorSinkControl->RemoveErrorSink(static_cast<IRMAErrorSink*>(this));
  142. m_pPlayer->RemoveAdviseSink(static_cast<IRMAClientAdviseSink*>(this));
  143. m_pVolume = NULL;
  144. m_pAudioPlayer->RemovePostMixHook(static_cast<IRMAAudioHook*>(this));
  145. m_pAudioPlayer.Release();
  146. m_pEngine->ClosePlayer(m_pPlayer);
  147. m_pSiteManager.Release();
  148. m_pCommonClassFactory.Release();
  149. m_pPlayer = NULL;
  150. }
  151. if(m_pEngine)
  152. {
  153. m_fpCloseEngine(m_pEngine);
  154. m_pEngine = NULL;
  155. }
  156. if(m_hRealMediaCore) 
  157. {
  158. FreeLibrary(m_hRealMediaCore);
  159. m_hRealMediaCore = NULL;
  160. }
  161. }
  162. STDMETHODIMP CRealMediaPlayer::NonDelegatingQueryInterface(REFIID riid, void** ppv)
  163. {
  164.     CheckPointer(ppv, E_POINTER);
  165. return 
  166. QI2(IRMAErrorSink)
  167. QI2(IRMAClientAdviseSink)
  168. QI2(IRMAAuthenticationManager)
  169. QI2(IRMASiteSupplier)
  170. QI2(IRMAPassiveSiteWatcher)
  171. QI2(IRMAAudioHook)
  172. __super::NonDelegatingQueryInterface(riid, ppv);
  173. }
  174. // IRMAErrorSink
  175. STDMETHODIMP CRealMediaPlayer::ErrorOccurred(const UINT8 unSeverity, const UINT32 ulRMACode, const UINT32 ulUserCode, const char* pUserString, const char* pMoreInfoURL)
  176. {
  177. char* errmsg = NULL;
  178. if(unSeverity < 5)
  179. {
  180. if(CComQIPtr<IRMAErrorMessages, &IID_IRMAErrorMessages> pErrorMessages = m_pPlayer)
  181. {
  182. CComPtr<IRMABuffer> pBuffer = pErrorMessages->GetErrorText(ulRMACode);
  183. if(pBuffer)
  184. {
  185. char* buff = (char*)pBuffer->GetBuffer();
  186. int len = strlen(buff);
  187. if(len > 0 && (errmsg = (char*)CoTaskMemAlloc(len+1)))
  188. strcpy(errmsg, buff);
  189. }
  190. }
  191. if(!errmsg && (errmsg = (char*)CoTaskMemAlloc(strlen("RealMedia error")+1)))
  192. strcpy(errmsg, "RealMedia error");
  193. m_pRMG->NotifyEvent(EC_BG_ERROR, (LONG_PTR)errmsg, 0);
  194. }
  195. return PNR_OK;
  196. }
  197. // IRMAClientAdviseSink
  198. STDMETHODIMP CRealMediaPlayer::OnPosLength(UINT32 ulPosition, UINT32 ulLength)
  199. {
  200. m_nCurrent = (REFERENCE_TIME)ulPosition*10000;
  201. m_nDuration = (REFERENCE_TIME)ulLength*10000;
  202. return PNR_OK;
  203. }
  204. STDMETHODIMP CRealMediaPlayer::OnPresentationOpened() {return PNR_OK;}
  205. STDMETHODIMP CRealMediaPlayer::OnPresentationClosed() {return PNR_OK;}
  206. STDMETHODIMP CRealMediaPlayer::OnStatisticsChanged() 
  207. {
  208. m_pRMG->NotifyEvent(EC_LENGTH_CHANGED);
  209. return PNR_OK;
  210. }
  211. STDMETHODIMP CRealMediaPlayer::OnPreSeek(UINT32 ulOldTime, UINT32 ulNewTime)
  212. {
  213. m_nCurrent = (REFERENCE_TIME)ulNewTime*10000;
  214. return PNR_OK;
  215. }
  216. STDMETHODIMP CRealMediaPlayer::OnPostSeek(UINT32 ulOldTime, UINT32 ulNewTime)
  217. {
  218. m_nCurrent = (REFERENCE_TIME)ulNewTime*10000;
  219. return PNR_OK;
  220. }
  221. STDMETHODIMP CRealMediaPlayer::OnStop()
  222. {
  223. m_nCurrent = 0;
  224. m_State = State_Stopped;
  225. if(m_UserState != State_Stopped)
  226. m_pRMG->NotifyEvent(EC_COMPLETE);
  227. return PNR_OK;
  228. }
  229. STDMETHODIMP CRealMediaPlayer::OnPause(UINT32 ulTime)
  230. {
  231. m_State = State_Paused;
  232. return PNR_OK;
  233. }
  234. STDMETHODIMP CRealMediaPlayer::OnBegin(UINT32 ulTime)
  235. {
  236. m_State = State_Running;
  237. return PNR_OK;
  238. }
  239. STDMETHODIMP CRealMediaPlayer::OnBuffering(UINT32 ulFlags, UINT16 unPercentComplete)
  240. {
  241. m_unPercentComplete = unPercentComplete;
  242. return PNR_OK;
  243. }
  244. STDMETHODIMP CRealMediaPlayer::OnContacting(const char* pHostName) {return PNR_OK;}
  245. // IRMAAuthenticationManager
  246. STDMETHODIMP CRealMediaPlayer::HandleAuthenticationRequest(IRMAAuthenticationManagerResponse* pResponse)
  247. {
  248. CAuthDlg dlg;
  249. if(dlg.DoModal() == IDOK)
  250. {
  251. pResponse->AuthenticationRequestDone(
  252. PNR_OK, CStringA(dlg.m_username), CStringA(dlg.m_password));
  253. return PNR_OK;
  254. }
  255. return pResponse->AuthenticationRequestDone(PNR_NOT_AUTHORIZED, NULL, NULL);
  256. }
  257. // IRMASiteSupplier
  258. STDMETHODIMP CRealMediaPlayer::SitesNeeded(UINT32 uRequestID, IRMAValues* pProps)
  259. {
  260.     if(!pProps) return PNR_INVALID_PARAMETER;
  261. if(m_pTheSite || m_pTheSite2 || !m_hWndParent) return PNR_UNEXPECTED;
  262. HRESULT hr = PNR_OK;
  263. if(!CreateSite(&m_pTheSite))
  264. return E_FAIL;
  265. ULONG refc = ((IRMASite*)m_pTheSite)->AddRef();
  266. refc = ((IRMASite*)m_pTheSite)->Release();
  267. if(!(m_pTheSite2 = m_pTheSite))
  268. return E_NOINTERFACE;
  269. CComQIPtr<IRMAValues, &IID_IRMAValues> pSiteProps = m_pTheSite;
  270.     if(!pSiteProps)
  271. return E_NOINTERFACE;
  272.     IRMABuffer* pValue;
  273. // no idea what these supposed to do... but they were in the example
  274.     hr = pProps->GetPropertyCString("playto", pValue);
  275.     if(PNR_OK == hr)
  276.     {
  277. pSiteProps->SetPropertyCString("channel", pValue);
  278. pValue->Release();
  279.     }
  280.     else
  281.     {
  282. hr = pProps->GetPropertyCString("name", pValue);
  283. if(PNR_OK == hr)
  284. {
  285. pSiteProps->SetPropertyCString("LayoutGroup", pValue);
  286. pValue->Release();
  287. }
  288.     }
  289.     m_pTheSite2->AddPassiveSiteWatcher(static_cast<IRMAPassiveSiteWatcher*>(this));
  290.     hr = m_pSiteManager->AddSite(m_pTheSite);
  291.     if(PNR_OK != hr)
  292. return hr;
  293.     m_CreatedSites[uRequestID] = m_pTheSite;
  294.     return hr;
  295. }
  296. STDMETHODIMP CRealMediaPlayer::SitesNotNeeded(UINT32 uRequestID)
  297. {
  298.     IRMASite* pSite;
  299. if(!m_CreatedSites.Lookup(uRequestID, pSite))
  300. return PNR_INVALID_PARAMETER;
  301. m_CreatedSites.RemoveKey(uRequestID);
  302.     m_pSiteManager->RemoveSite(pSite);
  303.     m_pTheSite2->RemovePassiveSiteWatcher(static_cast<IRMAPassiveSiteWatcher*>(this));
  304. m_pTheSite.Release();
  305. m_pTheSite2.Release();
  306. DestroySite(pSite);
  307.     return PNR_OK;
  308. }
  309. STDMETHODIMP CRealMediaPlayer::BeginChangeLayout() {return E_NOTIMPL;}
  310. STDMETHODIMP CRealMediaPlayer::DoneChangeLayout()
  311. {
  312. if(m_fVideoSizeChanged)
  313. {
  314.         m_pRMG->NotifyEvent(EC_VIDEO_SIZE_CHANGED, MAKELPARAM(m_VideoSize.cx, m_VideoSize.cy), 0);
  315. m_fVideoSizeChanged = false;
  316. }
  317. return PNR_OK;
  318. }
  319. // IRMAPassiveSiteWatcher
  320. STDMETHODIMP CRealMediaPlayer::PositionChanged(PNxPoint* pos) {return E_NOTIMPL;}
  321. STDMETHODIMP CRealMediaPlayer::SizeChanged(PNxSize* size)
  322. {
  323. if(m_VideoSize.cx == 0 || m_VideoSize.cy == 0)
  324. {
  325. m_fVideoSizeChanged = true;
  326. m_VideoSize.cx = size->cx;
  327. m_VideoSize.cy = size->cy;
  328. }
  329. return PNR_OK;
  330. }
  331. // IRMAAudioHook
  332. STDMETHODIMP CRealMediaPlayer::OnBuffer(RMAAudioData* pAudioInData, RMAAudioData* pAudioOutData) {return E_NOTIMPL;}
  333. STDMETHODIMP CRealMediaPlayer::OnInit(RMAAudioFormat* pFormat)
  334. {
  335. m_pRMG->NotifyEvent(EC_BG_AUDIO_CHANGED, pFormat->uChannels, 0);
  336. return PNR_OK;
  337. }
  338. //
  339. // CRealMediaPlayerWindowed
  340. //
  341. CRealMediaPlayerWindowed::CRealMediaPlayerWindowed(HWND hWndParent, CRealMediaGraph* pRMG) 
  342. : CRealMediaPlayer(hWndParent, pRMG) 
  343. {
  344. if(!m_wndWindowFrame.CreateEx(WS_EX_NOPARENTNOTIFY, NULL, NULL, WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_VISIBLE,
  345. CRect(0, 0, 0, 0), CWnd::FromHandle(m_hWndParent), 0, NULL))
  346. return;
  347. if(!m_wndDestFrame.Create(NULL, NULL, WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN,
  348. CRect(0, 0, 0, 0), &m_wndWindowFrame, 0, NULL))
  349. return;
  350. }
  351. CRealMediaPlayerWindowed::~CRealMediaPlayerWindowed()
  352. {
  353. m_wndDestFrame.DestroyWindow();
  354. m_wndWindowFrame.DestroyWindow();
  355. }
  356. void CRealMediaPlayerWindowed::SetWindowRect(CRect r)
  357. {
  358. if(IsWindow(m_wndWindowFrame.m_hWnd))
  359. m_wndWindowFrame.MoveWindow(r);
  360. }
  361. void CRealMediaPlayerWindowed::SetDestRect(CRect r)
  362. {
  363. if(IsWindow(m_wndDestFrame.m_hWnd))
  364. m_wndDestFrame.MoveWindow(r);
  365. if(m_pTheSite)
  366. {
  367. PNxSize s = {r.Width(), r.Height()};
  368. m_pTheSite->SetSize(s);
  369. }
  370. }
  371. bool CRealMediaPlayerWindowed::CreateSite(IRMASite** ppSite)
  372. {
  373. if(!ppSite)
  374. return(false);
  375.     CComPtr<IRMASiteWindowed> pSiteWindowed;
  376.     if(PNR_OK != m_pCommonClassFactory->CreateInstance(CLSID_IRMASiteWindowed, (void**)&pSiteWindowed))
  377. return(false);
  378. DWORD style = WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN;
  379. if(!AfxGetAppSettings().fIntRealMedia) style |= WS_DISABLED;
  380.     if(PNR_OK != pSiteWindowed->Create(m_wndDestFrame.m_hWnd, style))
  381. return(false);
  382. return !!(*ppSite = CComQIPtr<IRMASite, &IID_IRMASite>(pSiteWindowed).Detach());
  383. }
  384. void CRealMediaPlayerWindowed::DestroySite(IRMASite* pSite)
  385. {
  386. if(CComQIPtr<IRMASiteWindowed, &IID_IRMASiteWindowed> pRMASiteWindowed = pSite)
  387. pRMASiteWindowed->Destroy();
  388. }
  389. //
  390. // CRealMediaPlayerWindowless
  391. //
  392. CRealMediaPlayerWindowless::CRealMediaPlayerWindowless(HWND hWndParent, CRealMediaGraph* pRMG) 
  393. : CRealMediaPlayer(hWndParent, pRMG) 
  394. {
  395. AppSettings& s = AfxGetAppSettings();
  396. switch(s.iRMVideoRendererType)
  397. {
  398. default:
  399. case VIDRNDT_RM_DX7:
  400. if(FAILED(CreateAP7(CLSID_RM7AllocatorPresenter, hWndParent, &m_pRMAP)))
  401. return;
  402. break;
  403. case VIDRNDT_RM_DX9:
  404. if(FAILED(CreateAP9(CLSID_RM9AllocatorPresenter, hWndParent, &m_pRMAP)))
  405. return;
  406. break;
  407. }
  408. }
  409. CRealMediaPlayerWindowless::~CRealMediaPlayerWindowless()
  410. {
  411. }
  412. STDMETHODIMP CRealMediaPlayerWindowless::NonDelegatingQueryInterface(REFIID riid, void** ppv)
  413. {
  414.     CheckPointer(ppv, E_POINTER);
  415. return 
  416. (m_pRMAP && (riid == __uuidof(ISubPicAllocatorPresenter) || riid == IID_IRMAVideoSurface)) ? m_pRMAP->QueryInterface(riid, ppv) : 
  417. __super::NonDelegatingQueryInterface(riid, ppv);
  418. }
  419. bool CRealMediaPlayerWindowless::CreateSite(IRMASite** ppSite)
  420. {
  421. if(!ppSite || !m_pRMAP)
  422. return(false);
  423. HRESULT hr = S_OK;
  424. CRealMediaWindowlessSite* pWMWlS;
  425.     CComPtr<IRMASiteWindowless> pSiteWindowless;
  426. pSiteWindowless = (IRMASiteWindowless*)(pWMWlS = new CRealMediaWindowlessSite(hr, m_pPlayer, NULL, NULL));
  427.     if(FAILED(hr))
  428. return(false);
  429. pWMWlS->SetBltService(CComQIPtr<IRMAVideoSurface, &IID_IRMAVideoSurface>(m_pRMAP));
  430. return !!(*ppSite = CComQIPtr<IRMASite, &IID_IRMASite>(pSiteWindowless).Detach());
  431. }
  432. void CRealMediaPlayerWindowless::DestroySite(IRMASite* pSite)
  433. {
  434. }
  435. STDMETHODIMP CRealMediaPlayerWindowless::SizeChanged(PNxSize* size)
  436. {
  437. if(CComQIPtr<IRMAVideoSurface, &IID_IRMAVideoSurface> pRMAVS = m_pRMAP)
  438. {
  439. RMABitmapInfoHeader BitmapInfo;
  440. memset(&BitmapInfo, 0, sizeof(BitmapInfo));
  441. BitmapInfo.biWidth = size->cx;
  442. BitmapInfo.biHeight = size->cy;
  443. pRMAVS->BeginOptimizedBlt(&BitmapInfo);
  444. }
  445. return __super::SizeChanged(size);
  446. }
  447. ////////////////
  448. CRealMediaGraph::CRealMediaGraph(HWND hWndParent, HRESULT& hr)
  449. : CBaseGraph()
  450. {
  451. hr = S_OK;
  452. m_pRMP = AfxGetAppSettings().iRMVideoRendererType == VIDRNDT_RM_DEFAULT
  453. ? (CRealMediaPlayer*)new CRealMediaPlayerWindowed(hWndParent, this)
  454. : (CRealMediaPlayer*)new CRealMediaPlayerWindowless(hWndParent, this);
  455. if(!m_pRMP)
  456. {
  457. hr = E_OUTOFMEMORY;
  458. return;
  459. }
  460. if(!m_pRMP->Init())
  461. {
  462. delete m_pRMP, m_pRMP = NULL;
  463. hr = E_FAIL;
  464. return;
  465. }
  466. m_pRMP->AddRef();
  467. }
  468. CRealMediaGraph::~CRealMediaGraph()
  469. {
  470. if(m_pRMP)
  471. {
  472. m_pRMP->Deinit();
  473. m_pRMP->Release();
  474. m_pRMP = NULL;
  475. }
  476. }
  477. STDMETHODIMP CRealMediaGraph::NonDelegatingQueryInterface(REFIID riid, void** ppv)
  478. {
  479.     CheckPointer(ppv, E_POINTER);
  480. return 
  481. (m_pRMP && (riid == __uuidof(ISubPicAllocatorPresenter) || riid == __uuidof(ISubPicAllocatorPresenter))) ? m_pRMP->QueryInterface(riid, ppv) : 
  482. __super::NonDelegatingQueryInterface(riid, ppv);
  483. }
  484. // IGraphBuilder
  485. STDMETHODIMP CRealMediaGraph::RenderFile(LPCWSTR lpcwstrFile, LPCWSTR lpcwstrPlayList)
  486. {
  487. m_fn = lpcwstrFile;
  488. CHAR buff[MAX_PATH] = {0};
  489. WideCharToMultiByte(GetACP(), 0, lpcwstrFile, -1, buff, MAX_PATH, 0, 0);
  490. CStringA fn(buff);
  491. if(fn.Find("://") < 0) fn = "file://" + fn;
  492. m_pRMP->m_unPercentComplete = 100;
  493. ClearMessageQueue();
  494. if(PNR_OK != m_pRMP->m_pPlayer->OpenURL(fn)) 
  495. return E_FAIL;
  496. m_pRMP->m_pPlayer->Pause()/*Stop()*/; // please, don't start just yet
  497. return S_OK;
  498. }
  499. // IMediaControl
  500. STDMETHODIMP CRealMediaGraph::Run()
  501. {
  502. if(m_pRMP->m_pPlayer->IsDone())
  503. RenderFile(m_fn, NULL);
  504. m_pRMP->m_UserState = State_Running;
  505. return (PNR_OK == m_pRMP->m_pPlayer->Begin()) ? S_OK : E_FAIL;
  506. }
  507. STDMETHODIMP CRealMediaGraph::Pause()
  508. {
  509. m_pRMP->m_UserState = State_Paused;
  510. return (PNR_OK == m_pRMP->m_pPlayer->Pause()) ? S_OK : E_FAIL;
  511. }
  512. STDMETHODIMP CRealMediaGraph::Stop()
  513. {
  514. m_pRMP->m_UserState = State_Stopped;
  515. return (PNR_OK == m_pRMP->m_pPlayer->Stop()) ? S_OK : E_FAIL;
  516. }
  517. STDMETHODIMP CRealMediaGraph::GetState(LONG msTimeout, OAFilterState* pfs)
  518. {
  519. return pfs ? *pfs = m_pRMP->m_State, S_OK : E_POINTER;
  520. }
  521. // IMediaSeeking
  522. STDMETHODIMP CRealMediaGraph::GetDuration(LONGLONG* pDuration)
  523. {
  524. return pDuration ? *pDuration = m_pRMP->m_nDuration, S_OK : E_POINTER;
  525. }
  526. STDMETHODIMP CRealMediaGraph::GetCurrentPosition(LONGLONG* pCurrent)
  527. {
  528. return pCurrent ? *pCurrent = m_pRMP->m_nCurrent, S_OK : E_POINTER;
  529. }
  530. STDMETHODIMP CRealMediaGraph::SetPositions(LONGLONG* pCurrent, DWORD dwCurrentFlags, LONGLONG* pStop, DWORD dwStopFlags)
  531. {
  532. return (dwCurrentFlags&AM_SEEKING_AbsolutePositioning) 
  533. && (PNR_OK == m_pRMP->m_pPlayer->Seek((ULONG)(*pCurrent / 10000))) ? S_OK : E_FAIL;
  534. }
  535. // IVideoWindow
  536. STDMETHODIMP CRealMediaGraph::SetWindowPosition(long Left, long Top, long Width, long Height)
  537. {
  538. if(m_pRMP)
  539. m_pRMP->SetWindowRect(CRect(CPoint(Left, Top), CSize(Width, Height)));
  540. return S_OK;
  541. }
  542. // IBasicVideo
  543. STDMETHODIMP CRealMediaGraph::SetDestinationPosition(long Left, long Top, long Width, long Height)// {return E_NOTIMPL;}
  544. {
  545. m_pRMP->SetDestRect(CRect(CPoint(Left, Top), CSize(Width, Height)));
  546. return S_OK;
  547. }
  548. STDMETHODIMP CRealMediaGraph::GetVideoSize(long* pWidth, long* pHeight)
  549. {
  550. if(!pWidth || !pHeight) return E_POINTER;
  551. *pWidth = m_pRMP->GetVideoSize().cx;
  552. *pHeight = m_pRMP->GetVideoSize().cy;
  553. return S_OK;
  554. }
  555. // IBasicAudio
  556. STDMETHODIMP CRealMediaGraph::put_Volume(long lVolume)
  557. {
  558. if(!m_pRMP->m_pVolume) return E_UNEXPECTED;
  559. UINT16 volume = (lVolume == -10000) ? 0 : (int)pow(10.0, ((double)lVolume)/5000+2);
  560. volume = max(min(volume, 100), 0);
  561. return PNR_OK == m_pRMP->m_pVolume->SetVolume(volume) ? S_OK : E_FAIL;
  562. }
  563. STDMETHODIMP CRealMediaGraph::get_Volume(long* plVolume)
  564. {
  565. if(!m_pRMP->m_pVolume) return E_UNEXPECTED;
  566. CheckPointer(plVolume, E_POINTER);
  567. UINT16 volume = m_pRMP->m_pVolume->GetVolume();
  568. volume = (int)((log10(1.0*volume)-2)*5000);
  569. volume = max(min(volume, 0), -10000);
  570. *plVolume = volume;
  571. return S_OK;
  572. }
  573. // IAMOpenProgress
  574. STDMETHODIMP CRealMediaGraph::QueryProgress(LONGLONG* pllTotal, LONGLONG* pllCurrent)
  575. {
  576. *pllTotal = 100;
  577. *pllCurrent = m_pRMP->m_unPercentComplete > 0 ? m_pRMP->m_unPercentComplete : 100; // after seeking it drops to 0 and would show annoying "Buffering... (0%)" messages on the status line
  578. return S_OK;
  579. }
  580. // IGraphEngine
  581. STDMETHODIMP_(engine_t) CRealMediaGraph::GetEngine() {return RealMedia;}