- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# 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;}