RealMediaGraph.cpp

00001 /* 
00002  *      Copyright (C) 2003-2005 Gabest
00003  *      http://www.gabest.org
00004  *
00005  *  This Program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2, or (at your option)
00008  *  any later version.
00009  *   
00010  *  This Program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00013  *  GNU General Public License for more details.
00014  *   
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with GNU Make; see the file COPYING.  If not, write to
00017  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
00018  *  http://www.gnu.org/copyleft/gpl.html
00019  *
00020  */
00021 
00022 #include "stdafx.h"
00023 #include "mplayerc.h"
00024 #include <math.h>
00025 #include <atlbase.h>
00026 #include <atlcoll.h>
00027 #include <initguid.h>
00028 #include "RealMediaGraph.h"
00029 #include "RealMediaWindowlessSite.h"
00030 #include "..\..\..\include\RealMedia\rmavsurf.h"
00031 #include "..\..\..\include\RealMedia\rmaevent.h"
00032 #include "..\..\..\include\RealMedia\rmaprefs.h"
00033 #include "..\..\DSUtil\DSUtil.h"
00034 #include "AuthDlg.h"
00035 
00036 // CRealMediaPlayer
00037 
00038 CRealMediaPlayer::CRealMediaPlayer(HWND hWndParent, CRealMediaGraph* pRMG) 
00039         : CUnknown(NAME("CRealMediaPlayer"), NULL)
00040         , m_pRMG(pRMG)
00041         , m_hWndParent(hWndParent)
00042         , m_fpCreateEngine(NULL), m_fpCloseEngine(NULL), m_hRealMediaCore(NULL)
00043         , m_State(State_Stopped), m_UserState(State_Stopped), m_nCurrent(0), m_nDuration(0)
00044         , m_VideoSize(0, 0)
00045         , m_fVideoSizeChanged(true)
00046 {
00047 }
00048 
00049 CRealMediaPlayer::~CRealMediaPlayer()
00050 {
00051         Deinit();
00052 }
00053 
00054 bool CRealMediaPlayer::Init()
00055 {
00056         CString prefs(_T("Software\\RealNetworks\\Preferences"));
00057 
00058         CRegKey key;
00059 
00060         if(ERROR_SUCCESS != key.Open(HKEY_CLASSES_ROOT, prefs + _T("\\DT_Common"), KEY_READ))
00061                 return(false);
00062 
00063         TCHAR buff[MAX_PATH];
00064         ULONG len = sizeof(buff);
00065         if(ERROR_SUCCESS != key.QueryStringValue(NULL, buff, &len))
00066                 return(false);
00067 
00068         key.Close();
00069 
00070         if(!(m_hRealMediaCore = LoadLibrary(CString(buff) + _T("pnen3260.dll")))) 
00071                 return(false);
00072 
00073         m_fpCreateEngine = (FPRMCREATEENGINE)GetProcAddress(m_hRealMediaCore, "CreateEngine");
00074         m_fpCloseEngine = (FPRMCLOSEENGINE)GetProcAddress(m_hRealMediaCore, "CloseEngine");
00075         m_fpSetDLLAccessPath = (FPRMSETDLLACCESSPATH)GetProcAddress(m_hRealMediaCore, "SetDLLAccessPath");
00076         
00077         if(!m_fpCreateEngine || !m_fpCloseEngine || !m_fpSetDLLAccessPath)
00078                 return(false);
00079 
00080         if(ERROR_SUCCESS == key.Open(HKEY_CLASSES_ROOT, prefs, KEY_READ))
00081         {
00082                 CString dllpaths;
00083 
00084                 len = sizeof(buff);
00085                 for(int i = 0; ERROR_SUCCESS == key.EnumKey(i, buff, &len); i++, len = sizeof(buff))
00086                 {
00087                         CRegKey key2;
00088                         TCHAR buff2[MAX_PATH];
00089                         ULONG len2 = sizeof(buff2);
00090                         if(ERROR_SUCCESS != key2.Open(HKEY_CLASSES_ROOT, prefs + _T("\\") + buff, KEY_READ)
00091                         || ERROR_SUCCESS != key2.QueryStringValue(NULL, buff2, &len2))
00092                                 continue;
00093 
00094                         dllpaths += CString(buff) + '=' + buff2 + '|';
00095                 }
00096 
00097                 key.Close();
00098 
00099                 if(!dllpaths.IsEmpty())
00100                 {
00101                         char* s = new char[dllpaths.GetLength()+1];
00102                         strcpy(s, CStringA(dllpaths));
00103                         for(int i = 0, j = strlen(s); i < j; i++) {if(s[i] == '|') s[i] = '\0';}
00104                         m_fpSetDLLAccessPath(s);
00105                         delete [] s;
00106                 }
00107         }
00108 
00109         if(PNR_OK != m_fpCreateEngine(&m_pEngine))
00110                 return(false);
00111 
00112         if(PNR_OK != m_pEngine->CreatePlayer(*&m_pPlayer))
00113                 return(false);
00114 
00115         if(!(m_pSiteManager = m_pPlayer) || !(m_pCommonClassFactory = m_pPlayer))
00116                 return(false);
00117 
00118         m_pAudioPlayer = m_pPlayer;
00119         m_pAudioPlayer->AddPostMixHook(static_cast<IRMAAudioHook*>(this), FALSE, FALSE);
00120 //      m_pVolume = m_pAudioPlayer->GetDeviceVolume();
00121         m_pVolume = m_pAudioPlayer->GetAudioVolume();
00122 
00123         // IRMAVolume::SetVolume has a huge latency when used via GetAudioVolume,
00124         // but by lowering this audio pushdown thing it can get better
00125         CComQIPtr<IRMAAudioPushdown, &IID_IRMAAudioPushdown> pAP = m_pAudioPlayer;
00126         if(pAP) pAP->SetAudioPushdown(300); // 100ms makes the playback sound choppy, 200ms looks ok, but for safety we set this to 300ms... :P
00127 
00128         CComQIPtr<IRMAErrorSinkControl, &IID_IRMAErrorSinkControl> pErrorSinkControl = m_pPlayer;
00129         if(pErrorSinkControl) pErrorSinkControl->AddErrorSink(static_cast<IRMAErrorSink*>(this), PNLOG_EMERG, PNLOG_INFO);
00130 
00131         if(PNR_OK != m_pPlayer->AddAdviseSink(static_cast<IRMAClientAdviseSink*>(this)))
00132                 return(false);
00133 
00134         if(PNR_OK != m_pPlayer->SetClientContext((IUnknown*)(INonDelegatingUnknown*)(this)))
00135                 return(false);
00136 
00137         // TODO
00138 /*
00139         if(CComQIPtr<IRMAPreferences, &IID_IRMAPreferences> pPrefs = m_pPlayer)
00140         {
00141                 CComPtr<IRMABuffer> pBuffer;
00142                 HRESULT hr = pPrefs->ReadPref("HTTPProxyHost", *&pBuffer);
00143 
00144                 UCHAR* pData = NULL;
00145                 ULONG32 ulLength = 0;
00146                 hr = pBuffer->Get(pData, ulLength);
00147 
00148                 pBuffer = NULL;
00149                 hr = m_pCommonClassFactory->CreateInstance(CLSID_IRMABuffer, (void**)&pBuffer);
00150                 hr = pBuffer->SetSize(strlen("localhost")+1);
00151                 pData = pBuffer->GetBuffer();
00152                 strcpy((char*)pData, "localhost");
00153                 hr = pBuffer->Set(pData, strlen("localhost")+1);
00154 
00155                 pData = NULL;
00156                 ulLength = 0;
00157                 hr = pBuffer->Get(pData, ulLength);
00158 
00159                 hr = pPrefs->WritePref("HTTPProxyHost", pBuffer);
00160 
00161                 hr = hr;
00162         }
00163 */
00164         return(true);
00165 }
00166 
00167 void CRealMediaPlayer::Deinit()
00168 {
00169         if(m_pPlayer)
00170         {
00171                 m_pPlayer->Stop();
00172 
00173                 CComQIPtr<IRMAErrorSinkControl, &IID_IRMAErrorSinkControl> pErrorSinkControl = m_pPlayer;
00174                 if(pErrorSinkControl) pErrorSinkControl->RemoveErrorSink(static_cast<IRMAErrorSink*>(this));
00175 
00176                 m_pPlayer->RemoveAdviseSink(static_cast<IRMAClientAdviseSink*>(this));
00177 
00178                 m_pVolume = NULL;
00179                 m_pAudioPlayer->RemovePostMixHook(static_cast<IRMAAudioHook*>(this));
00180                 m_pAudioPlayer.Release();
00181 
00182                 m_pEngine->ClosePlayer(m_pPlayer);
00183 
00184                 m_pSiteManager.Release();
00185                 m_pCommonClassFactory.Release();
00186 
00187                 m_pPlayer = NULL;
00188         }
00189 
00190         if(m_pEngine)
00191         {
00192                 m_fpCloseEngine(m_pEngine);
00193                 m_pEngine = NULL;
00194         }
00195 
00196         if(m_hRealMediaCore) 
00197         {
00198                 FreeLibrary(m_hRealMediaCore);
00199                 m_hRealMediaCore = NULL;
00200         }
00201 }
00202 
00203 STDMETHODIMP CRealMediaPlayer::NonDelegatingQueryInterface(REFIID riid, void** ppv)
00204 {
00205     CheckPointer(ppv, E_POINTER);
00206 
00207         return 
00208                 QI2(IRMAErrorSink)
00209                 QI2(IRMAClientAdviseSink)
00210                 QI2(IRMAAuthenticationManager)
00211                 QI2(IRMASiteSupplier)
00212                 QI2(IRMAPassiveSiteWatcher)
00213                 QI2(IRMAAudioHook)
00214                 __super::NonDelegatingQueryInterface(riid, ppv);
00215 }
00216 
00217 // IRMAErrorSink
00218 STDMETHODIMP CRealMediaPlayer::ErrorOccurred(const UINT8 unSeverity, const UINT32 ulRMACode, const UINT32 ulUserCode, const char* pUserString, const char* pMoreInfoURL)
00219 {
00220         char* errmsg = NULL;
00221 
00222         if(unSeverity < 5)
00223         {
00224                 if(CComQIPtr<IRMAErrorMessages, &IID_IRMAErrorMessages> pErrorMessages = m_pPlayer)
00225                 {
00226                         CComPtr<IRMABuffer> pBuffer = pErrorMessages->GetErrorText(ulRMACode);
00227                         if(pBuffer)
00228                         {
00229                                 char* buff = (char*)pBuffer->GetBuffer();
00230                                 int len = strlen(buff);
00231                                 if(len > 0 && (errmsg = (char*)CoTaskMemAlloc(len+1)))
00232                                         strcpy(errmsg, buff);
00233                         }
00234                 }
00235 
00236                 if(!errmsg && (errmsg = (char*)CoTaskMemAlloc(strlen("RealMedia error")+1)))
00237                         strcpy(errmsg, "RealMedia error");              
00238 
00239                 m_pRMG->NotifyEvent(EC_BG_ERROR, (LONG_PTR)errmsg, 0);
00240         }
00241 
00242         return PNR_OK;
00243 }
00244 
00245 // IRMAClientAdviseSink
00246 STDMETHODIMP CRealMediaPlayer::OnPosLength(UINT32 ulPosition, UINT32 ulLength)
00247 {
00248         m_nCurrent = (REFERENCE_TIME)ulPosition*10000;
00249         m_nDuration = (REFERENCE_TIME)ulLength*10000;
00250         return PNR_OK;
00251 }
00252 STDMETHODIMP CRealMediaPlayer::OnPresentationOpened() {return PNR_OK;}
00253 STDMETHODIMP CRealMediaPlayer::OnPresentationClosed() {return PNR_OK;}
00254 STDMETHODIMP CRealMediaPlayer::OnStatisticsChanged() 
00255 {
00256         m_pRMG->NotifyEvent(EC_LENGTH_CHANGED); 
00257         return PNR_OK;
00258 }
00259 STDMETHODIMP CRealMediaPlayer::OnPreSeek(UINT32 ulOldTime, UINT32 ulNewTime)
00260 {
00261         m_nCurrent = (REFERENCE_TIME)ulNewTime*10000;
00262         return PNR_OK;
00263 }
00264 STDMETHODIMP CRealMediaPlayer::OnPostSeek(UINT32 ulOldTime, UINT32 ulNewTime)
00265 {
00266         m_nCurrent = (REFERENCE_TIME)ulNewTime*10000;
00267         return PNR_OK;
00268 }
00269 STDMETHODIMP CRealMediaPlayer::OnStop()
00270 {
00271         m_nCurrent = 0;
00272         m_State = State_Stopped;
00273         if(m_UserState != State_Stopped)
00274                 m_pRMG->NotifyEvent(EC_COMPLETE);
00275         return PNR_OK;
00276 }
00277 STDMETHODIMP CRealMediaPlayer::OnPause(UINT32 ulTime)
00278 {
00279         m_State = State_Paused;
00280         return PNR_OK;
00281 }
00282 STDMETHODIMP CRealMediaPlayer::OnBegin(UINT32 ulTime)
00283 {
00284         m_State = State_Running;
00285         return PNR_OK;
00286 }
00287 STDMETHODIMP CRealMediaPlayer::OnBuffering(UINT32 ulFlags, UINT16 unPercentComplete)
00288 {
00289         m_unPercentComplete = unPercentComplete;
00290         return PNR_OK;
00291 }
00292 STDMETHODIMP CRealMediaPlayer::OnContacting(const char* pHostName) {return PNR_OK;}
00293 
00294 // IRMAAuthenticationManager
00295 STDMETHODIMP CRealMediaPlayer::HandleAuthenticationRequest(IRMAAuthenticationManagerResponse* pResponse)
00296 {
00297         CAuthDlg dlg;
00298 
00299         if(dlg.DoModal() == IDOK)
00300         {
00301                 pResponse->AuthenticationRequestDone(
00302                         PNR_OK, CStringA(dlg.m_username), CStringA(dlg.m_password));
00303                 return PNR_OK;
00304         }
00305 
00306         return pResponse->AuthenticationRequestDone(PNR_NOT_AUTHORIZED, NULL, NULL);
00307 }
00308 
00309 // IRMASiteSupplier
00310 STDMETHODIMP CRealMediaPlayer::SitesNeeded(UINT32 uRequestID, IRMAValues* pProps)
00311 {
00312     if(!pProps) return PNR_INVALID_PARAMETER;
00313 
00314         if(m_pTheSite || m_pTheSite2 || !m_hWndParent) return PNR_UNEXPECTED;
00315 
00316         HRESULT hr = PNR_OK;
00317 
00318         if(!CreateSite(&m_pTheSite))
00319                 return E_FAIL;
00320 
00321         ULONG refc = ((IRMASite*)m_pTheSite)->AddRef();
00322         refc = ((IRMASite*)m_pTheSite)->Release();
00323 
00324         if(!(m_pTheSite2 = m_pTheSite))
00325                 return E_NOINTERFACE;
00326 
00327         CComQIPtr<IRMAValues, &IID_IRMAValues> pSiteProps = m_pTheSite;
00328     if(!pSiteProps)
00329                 return E_NOINTERFACE;
00330 
00331     IRMABuffer* pValue;
00332 
00333         // no idea what these supposed to do... but they were in the example
00334     hr = pProps->GetPropertyCString("playto", pValue);
00335     if(PNR_OK == hr)
00336     {
00337                 pSiteProps->SetPropertyCString("channel", pValue);
00338                 pValue->Release();
00339     }
00340     else
00341     {
00342                 hr = pProps->GetPropertyCString("name", pValue);
00343                 if(PNR_OK == hr)
00344                 {
00345                         pSiteProps->SetPropertyCString("LayoutGroup", pValue);
00346                         pValue->Release();
00347                 }
00348     }
00349 
00350     m_pTheSite2->AddPassiveSiteWatcher(static_cast<IRMAPassiveSiteWatcher*>(this));
00351 
00352     hr = m_pSiteManager->AddSite(m_pTheSite);
00353     if(PNR_OK != hr)
00354                 return hr;
00355 
00356     m_CreatedSites[uRequestID] = m_pTheSite;
00357 
00358     return hr;
00359 }
00360 
00361 STDMETHODIMP CRealMediaPlayer::SitesNotNeeded(UINT32 uRequestID)
00362 {
00363     IRMASite* pSite;
00364         if(!m_CreatedSites.Lookup(uRequestID, pSite))
00365                 return PNR_INVALID_PARAMETER;
00366 
00367         m_CreatedSites.RemoveKey(uRequestID);
00368 
00369     m_pSiteManager->RemoveSite(pSite);
00370 
00371     m_pTheSite2->RemovePassiveSiteWatcher(static_cast<IRMAPassiveSiteWatcher*>(this));
00372 
00373         m_pTheSite.Release();
00374         m_pTheSite2.Release();
00375 
00376         DestroySite(pSite);
00377 
00378     return PNR_OK;
00379 }
00380 STDMETHODIMP CRealMediaPlayer::BeginChangeLayout() {return E_NOTIMPL;}
00381 STDMETHODIMP CRealMediaPlayer::DoneChangeLayout()
00382 {
00383         if(m_fVideoSizeChanged)
00384         {
00385         m_pRMG->NotifyEvent(EC_VIDEO_SIZE_CHANGED, MAKELPARAM(m_VideoSize.cx, m_VideoSize.cy), 0);
00386                 m_fVideoSizeChanged = false;
00387         }
00388 
00389         return PNR_OK;
00390 }
00391 
00392 // IRMAPassiveSiteWatcher
00393 STDMETHODIMP CRealMediaPlayer::PositionChanged(PNxPoint* pos) {return E_NOTIMPL;}
00394 STDMETHODIMP CRealMediaPlayer::SizeChanged(PNxSize* size)
00395 {
00396         if(m_VideoSize.cx == 0 || m_VideoSize.cy == 0)
00397         {
00398                 m_fVideoSizeChanged = true;
00399                 m_VideoSize.cx = size->cx;
00400                 m_VideoSize.cy = size->cy;
00401         }
00402         return PNR_OK;
00403 }
00404 
00405 // IRMAAudioHook
00406 STDMETHODIMP CRealMediaPlayer::OnBuffer(RMAAudioData* pAudioInData, RMAAudioData* pAudioOutData) {return E_NOTIMPL;}
00407 STDMETHODIMP CRealMediaPlayer::OnInit(RMAAudioFormat* pFormat)
00408 {
00409         m_pRMG->NotifyEvent(EC_BG_AUDIO_CHANGED, pFormat->uChannels, 0);
00410         return PNR_OK;
00411 }
00412 
00413 //
00414 // CRealMediaPlayerWindowed
00415 //
00416 
00417 CRealMediaPlayerWindowed::CRealMediaPlayerWindowed(HWND hWndParent, CRealMediaGraph* pRMG) 
00418         : CRealMediaPlayer(hWndParent, pRMG) 
00419 {
00420         if(!m_wndWindowFrame.CreateEx(WS_EX_NOPARENTNOTIFY, NULL, NULL, WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_VISIBLE,
00421                 CRect(0, 0, 0, 0), CWnd::FromHandle(m_hWndParent), 0, NULL))
00422                 return;
00423 
00424         if(!m_wndDestFrame.Create(NULL, NULL, WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN,
00425                 CRect(0, 0, 0, 0), &m_wndWindowFrame, 0, NULL))
00426                 return;
00427 }
00428 
00429 CRealMediaPlayerWindowed::~CRealMediaPlayerWindowed()
00430 {
00431         m_wndDestFrame.DestroyWindow();
00432         m_wndWindowFrame.DestroyWindow();
00433 }
00434 
00435 void CRealMediaPlayerWindowed::SetWindowRect(CRect r)
00436 {
00437         if(IsWindow(m_wndWindowFrame.m_hWnd))
00438                 m_wndWindowFrame.MoveWindow(r);
00439 }
00440 
00441 void CRealMediaPlayerWindowed::SetDestRect(CRect r)
00442 {
00443         if(IsWindow(m_wndDestFrame.m_hWnd))
00444                 m_wndDestFrame.MoveWindow(r);
00445 
00446         if(m_pTheSite)
00447         {
00448                 PNxSize s = {r.Width(), r.Height()};
00449                 m_pTheSite->SetSize(s);
00450         }
00451 }
00452 
00453 bool CRealMediaPlayerWindowed::CreateSite(IRMASite** ppSite)
00454 {
00455         if(!ppSite)
00456                 return(false);
00457 
00458     CComPtr<IRMASiteWindowed> pSiteWindowed;
00459     if(PNR_OK != m_pCommonClassFactory->CreateInstance(CLSID_IRMASiteWindowed, (void**)&pSiteWindowed))
00460                 return(false);
00461 
00462         DWORD style = WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN;
00463         if(!AfxGetAppSettings().fIntRealMedia) style |= WS_DISABLED;
00464     if(PNR_OK != pSiteWindowed->Create(m_wndDestFrame.m_hWnd, style))
00465                 return(false);
00466 
00467         return !!(*ppSite = CComQIPtr<IRMASite, &IID_IRMASite>(pSiteWindowed).Detach());
00468 }
00469 
00470 void CRealMediaPlayerWindowed::DestroySite(IRMASite* pSite)
00471 {
00472         if(CComQIPtr<IRMASiteWindowed, &IID_IRMASiteWindowed> pRMASiteWindowed = pSite)
00473                 pRMASiteWindowed->Destroy();
00474 }
00475 //
00476 // CRealMediaPlayerWindowless
00477 //
00478 
00479 CRealMediaPlayerWindowless::CRealMediaPlayerWindowless(HWND hWndParent, CRealMediaGraph* pRMG) 
00480         : CRealMediaPlayer(hWndParent, pRMG) 
00481 {
00482         AppSettings& s = AfxGetAppSettings();
00483 
00484         switch(s.iRMVideoRendererType)
00485         {
00486         default:
00487         case VIDRNDT_RM_DX7:
00488                 if(FAILED(CreateAP7(CLSID_RM7AllocatorPresenter, hWndParent, &m_pRMAP)))
00489                         return;
00490                 break;
00491         case VIDRNDT_RM_DX9:
00492                 if(FAILED(CreateAP9(CLSID_RM9AllocatorPresenter, hWndParent, &m_pRMAP)))
00493                         return;
00494                 break;
00495         }
00496 }
00497 
00498 CRealMediaPlayerWindowless::~CRealMediaPlayerWindowless()
00499 {
00500 }
00501 
00502 STDMETHODIMP CRealMediaPlayerWindowless::NonDelegatingQueryInterface(REFIID riid, void** ppv)
00503 {
00504     CheckPointer(ppv, E_POINTER);
00505 
00506         return 
00507                 (m_pRMAP && (riid == __uuidof(ISubPicAllocatorPresenter) || riid == IID_IRMAVideoSurface)) ? m_pRMAP->QueryInterface(riid, ppv) : 
00508                 __super::NonDelegatingQueryInterface(riid, ppv);
00509 }
00510 
00511 bool CRealMediaPlayerWindowless::CreateSite(IRMASite** ppSite)
00512 {
00513         if(!ppSite || !m_pRMAP)
00514                 return(false);
00515 
00516         HRESULT hr = S_OK;
00517 
00518         CRealMediaWindowlessSite* pWMWlS;
00519 
00520     CComPtr<IRMASiteWindowless> pSiteWindowless;
00521         pSiteWindowless = (IRMASiteWindowless*)(pWMWlS = new CRealMediaWindowlessSite(hr, m_pPlayer, NULL, NULL));
00522     if(FAILED(hr))
00523                 return(false);
00524 
00525         pWMWlS->SetBltService(CComQIPtr<IRMAVideoSurface, &IID_IRMAVideoSurface>(m_pRMAP));
00526 
00527         return !!(*ppSite = CComQIPtr<IRMASite, &IID_IRMASite>(pSiteWindowless).Detach());
00528 }
00529 
00530 void CRealMediaPlayerWindowless::DestroySite(IRMASite* pSite)
00531 {
00532 }
00533 
00534 STDMETHODIMP CRealMediaPlayerWindowless::SizeChanged(PNxSize* size)
00535 {
00536         if(CComQIPtr<IRMAVideoSurface, &IID_IRMAVideoSurface> pRMAVS = m_pRMAP)
00537         {
00538                 RMABitmapInfoHeader BitmapInfo;
00539                 memset(&BitmapInfo, 0, sizeof(BitmapInfo));
00540                 BitmapInfo.biWidth = size->cx;
00541                 BitmapInfo.biHeight = size->cy;
00542                 pRMAVS->BeginOptimizedBlt(&BitmapInfo);
00543         }
00544 
00545         return __super::SizeChanged(size);
00546 }
00547 
00548 
00550 
00551 CRealMediaGraph::CRealMediaGraph(HWND hWndParent, HRESULT& hr)
00552         : CBaseGraph()
00553 {
00554         hr = S_OK;
00555 
00556         m_pRMP = AfxGetAppSettings().iRMVideoRendererType == VIDRNDT_RM_DEFAULT
00557                 ? (CRealMediaPlayer*)new CRealMediaPlayerWindowed(hWndParent, this)
00558                 : (CRealMediaPlayer*)new CRealMediaPlayerWindowless(hWndParent, this);
00559 
00560         if(!m_pRMP)
00561         {
00562                 hr = E_OUTOFMEMORY;
00563                 return;
00564         }
00565 
00566         if(!m_pRMP->Init())
00567         {
00568                 delete m_pRMP, m_pRMP = NULL;
00569                 hr = E_FAIL;
00570                 return;
00571         }
00572 
00573         m_pRMP->AddRef();
00574 }
00575 
00576 CRealMediaGraph::~CRealMediaGraph()
00577 {
00578         if(m_pRMP)
00579         {
00580                 m_pRMP->Deinit();
00581                 m_pRMP->Release();
00582                 m_pRMP = NULL;
00583         }
00584 }
00585 
00586 STDMETHODIMP CRealMediaGraph::NonDelegatingQueryInterface(REFIID riid, void** ppv)
00587 {
00588     CheckPointer(ppv, E_POINTER);
00589 
00590         return 
00591                 (m_pRMP && (riid == __uuidof(ISubPicAllocatorPresenter) || riid == __uuidof(ISubPicAllocatorPresenter))) ? m_pRMP->QueryInterface(riid, ppv) : 
00592                 __super::NonDelegatingQueryInterface(riid, ppv);
00593 }
00594 
00595 // IGraphBuilder
00596 STDMETHODIMP CRealMediaGraph::RenderFile(LPCWSTR lpcwstrFile, LPCWSTR lpcwstrPlayList)
00597 {
00598         CHAR buff[MAX_PATH] = {0};
00599         WideCharToMultiByte(GetACP(), 0, lpcwstrFile, -1, buff, MAX_PATH, 0, 0);
00600 
00601         CStringA fn(buff);
00602         if(fn.Find("://") < 0) fn = "file://" + fn;
00603 
00604         m_pRMP->m_unPercentComplete = 100;
00605 
00606         ClearMessageQueue();
00607 
00608         if(PNR_OK != m_pRMP->m_pPlayer->OpenURL(fn)) 
00609                 return E_FAIL;
00610 
00611         m_pRMP->m_pPlayer->Pause()/*Stop()*/; // please, don't start just yet
00612 
00613         return S_OK;
00614 }
00615 
00616 // IMediaControl
00617 STDMETHODIMP CRealMediaGraph::Run()
00618 {
00619         m_pRMP->m_UserState = State_Running;
00620         return (PNR_OK == m_pRMP->m_pPlayer->Begin()) ? S_OK : E_FAIL;
00621 }
00622 STDMETHODIMP CRealMediaGraph::Pause()
00623 {
00624         m_pRMP->m_UserState = State_Paused;
00625         return (PNR_OK == m_pRMP->m_pPlayer->Pause()) ? S_OK : E_FAIL;
00626 }
00627 STDMETHODIMP CRealMediaGraph::Stop()
00628 {
00629         m_pRMP->m_UserState = State_Stopped;
00630         return (PNR_OK == m_pRMP->m_pPlayer->Stop()) ? S_OK : E_FAIL;
00631 }
00632 STDMETHODIMP CRealMediaGraph::GetState(LONG msTimeout, OAFilterState* pfs)
00633 {
00634         return pfs ? *pfs = m_pRMP->m_State, S_OK : E_POINTER;
00635 }
00636 
00637 // IMediaSeeking
00638 STDMETHODIMP CRealMediaGraph::GetDuration(LONGLONG* pDuration)
00639 {
00640         return pDuration ? *pDuration = m_pRMP->m_nDuration, S_OK : E_POINTER;
00641 }
00642 STDMETHODIMP CRealMediaGraph::GetCurrentPosition(LONGLONG* pCurrent)
00643 {
00644         return pCurrent ? *pCurrent = m_pRMP->m_nCurrent, S_OK : E_POINTER;
00645 }
00646 STDMETHODIMP CRealMediaGraph::SetPositions(LONGLONG* pCurrent, DWORD dwCurrentFlags, LONGLONG* pStop, DWORD dwStopFlags)
00647 {
00648         return (dwCurrentFlags&AM_SEEKING_AbsolutePositioning) 
00649                 && (PNR_OK == m_pRMP->m_pPlayer->Seek((ULONG)(*pCurrent / 10000))) ? S_OK : E_FAIL;
00650 }
00651 
00652 // IVideoWindow
00653 STDMETHODIMP CRealMediaGraph::SetWindowPosition(long Left, long Top, long Width, long Height)
00654 {
00655         if(m_pRMP)
00656                 m_pRMP->SetWindowRect(CRect(CPoint(Left, Top), CSize(Width, Height)));
00657 
00658         return S_OK;
00659 }
00660 
00661 // IBasicVideo
00662 STDMETHODIMP CRealMediaGraph::SetDestinationPosition(long Left, long Top, long Width, long Height)// {return E_NOTIMPL;}
00663 {
00664         m_pRMP->SetDestRect(CRect(CPoint(Left, Top), CSize(Width, Height)));
00665         return S_OK;
00666 }
00667 STDMETHODIMP CRealMediaGraph::GetVideoSize(long* pWidth, long* pHeight)
00668 {
00669         if(!pWidth || !pHeight) return E_POINTER;
00670         *pWidth = m_pRMP->GetVideoSize().cx;
00671         *pHeight = m_pRMP->GetVideoSize().cy;
00672         return S_OK;
00673 }
00674 
00675 // IBasicAudio
00676 STDMETHODIMP CRealMediaGraph::put_Volume(long lVolume)
00677 {
00678         if(!m_pRMP->m_pVolume) return E_UNEXPECTED;
00679 
00680         UINT16 volume = (lVolume == -10000) ? 0 : (int)pow(10.0, ((double)lVolume)/5000+2);
00681         volume = max(min(volume, 100), 0);
00682 
00683         return PNR_OK == m_pRMP->m_pVolume->SetVolume(volume) ? S_OK : E_FAIL;
00684 }
00685 STDMETHODIMP CRealMediaGraph::get_Volume(long* plVolume)
00686 {
00687         if(!m_pRMP->m_pVolume) return E_UNEXPECTED;
00688 
00689         CheckPointer(plVolume, E_POINTER);
00690 
00691         UINT16 volume = m_pRMP->m_pVolume->GetVolume();
00692         volume = (int)((log10(1.0*volume)-2)*5000);
00693         volume = max(min(volume, 0), -10000);
00694 
00695         *plVolume = volume;
00696 
00697         return S_OK;
00698 }
00699 
00700 // IAMOpenProgress
00701 STDMETHODIMP CRealMediaGraph::QueryProgress(LONGLONG* pllTotal, LONGLONG* pllCurrent)
00702 {
00703         *pllTotal = 100;
00704         *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
00705         return S_OK;
00706 }
00707 
00708 // IGraphEngine
00709 STDMETHODIMP_(engine_t) CRealMediaGraph::GetEngine() {return RealMedia;}

Generated on Tue Dec 13 14:47:03 2005 for guliverkli by  doxygen 1.4.5