Support unrar64.dll
[xy_vsfilter.git] / src / apps / mplayerc / RealMediaGraph.cpp
blob719b5282c4af73eeb70d8be23133c69a5e6a3d75
1 /*
2 * Copyright (C) 2003-2006 Gabest
3 * http://www.gabest.org
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.
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
22 #include "stdafx.h"
23 #include "mplayerc.h"
24 #include <math.h>
25 #include <atlbase.h>
26 #include <atlcoll.h>
27 #include <initguid.h>
28 #include "RealMediaGraph.h"
29 #include "RealMediaWindowlessSite.h"
30 #include "..\..\..\include\RealMedia\rmavsurf.h"
31 #include "..\..\..\include\RealMedia\rmaevent.h"
32 #include "..\..\..\include\RealMedia\rmaprefs.h"
33 #include "..\..\DSUtil\DSUtil.h"
34 #include "AuthDlg.h"
36 // CRealMediaPlayer
38 CRealMediaPlayer::CRealMediaPlayer(HWND hWndParent, CRealMediaGraph* pRMG)
39 : CUnknown(NAME("CRealMediaPlayer"), NULL)
40 , m_pRMG(pRMG)
41 , m_hWndParent(hWndParent)
42 , m_fpCreateEngine(NULL), m_fpCloseEngine(NULL), m_hRealMediaCore(NULL)
43 , m_State(State_Stopped), m_UserState(State_Stopped), m_nCurrent(0), m_nDuration(0)
44 , m_VideoSize(0, 0)
45 , m_fVideoSizeChanged(true)
49 CRealMediaPlayer::~CRealMediaPlayer()
51 Deinit();
54 bool CRealMediaPlayer::Init()
56 CString prefs(_T("Software\\RealNetworks\\Preferences"));
58 CRegKey key;
60 if(ERROR_SUCCESS != key.Open(HKEY_CLASSES_ROOT, prefs + _T("\\DT_Common"), KEY_READ))
61 return(false);
63 TCHAR buff[MAX_PATH];
64 ULONG len = sizeof(buff);
65 if(ERROR_SUCCESS != key.QueryStringValue(NULL, buff, &len))
66 return(false);
68 key.Close();
70 if(!(m_hRealMediaCore = LoadLibrary(CString(buff) + _T("pnen3260.dll"))))
71 return(false);
73 m_fpCreateEngine = (FPRMCREATEENGINE)GetProcAddress(m_hRealMediaCore, "CreateEngine");
74 m_fpCloseEngine = (FPRMCLOSEENGINE)GetProcAddress(m_hRealMediaCore, "CloseEngine");
75 m_fpSetDLLAccessPath = (FPRMSETDLLACCESSPATH)GetProcAddress(m_hRealMediaCore, "SetDLLAccessPath");
77 if(!m_fpCreateEngine || !m_fpCloseEngine || !m_fpSetDLLAccessPath)
78 return(false);
80 if(ERROR_SUCCESS == key.Open(HKEY_CLASSES_ROOT, prefs, KEY_READ))
82 CString dllpaths;
84 len = sizeof(buff);
85 for(int i = 0; ERROR_SUCCESS == key.EnumKey(i, buff, &len); i++, len = sizeof(buff))
87 CRegKey key2;
88 TCHAR buff2[MAX_PATH];
89 ULONG len2 = sizeof(buff2);
90 if(ERROR_SUCCESS != key2.Open(HKEY_CLASSES_ROOT, prefs + _T("\\") + buff, KEY_READ)
91 || ERROR_SUCCESS != key2.QueryStringValue(NULL, buff2, &len2))
92 continue;
94 dllpaths += CString(buff) + '=' + buff2 + '|';
97 key.Close();
99 if(!dllpaths.IsEmpty())
101 char* s = new char[dllpaths.GetLength()+1];
102 strcpy(s, CStringA(dllpaths));
103 for(int i = 0, j = strlen(s); i < j; i++) {if(s[i] == '|') s[i] = '\0';}
104 m_fpSetDLLAccessPath(s);
105 delete [] s;
109 if(PNR_OK != m_fpCreateEngine(&m_pEngine))
110 return(false);
112 if(PNR_OK != m_pEngine->CreatePlayer(*&m_pPlayer))
113 return(false);
115 if(!(m_pSiteManager = m_pPlayer) || !(m_pCommonClassFactory = m_pPlayer))
116 return(false);
118 m_pAudioPlayer = m_pPlayer;
119 m_pAudioPlayer->AddPostMixHook(static_cast<IRMAAudioHook*>(this), FALSE, FALSE);
120 // m_pVolume = m_pAudioPlayer->GetDeviceVolume();
121 m_pVolume = m_pAudioPlayer->GetAudioVolume();
123 // IRMAVolume::SetVolume has a huge latency when used via GetAudioVolume,
124 // but by lowering this audio pushdown thing it can get better
125 CComQIPtr<IRMAAudioPushdown, &IID_IRMAAudioPushdown> pAP = m_pAudioPlayer;
126 if(pAP) pAP->SetAudioPushdown(300); // 100ms makes the playback sound choppy, 200ms looks ok, but for safety we set this to 300ms... :P
128 CComQIPtr<IRMAErrorSinkControl, &IID_IRMAErrorSinkControl> pErrorSinkControl = m_pPlayer;
129 if(pErrorSinkControl) pErrorSinkControl->AddErrorSink(static_cast<IRMAErrorSink*>(this), PNLOG_EMERG, PNLOG_INFO);
131 if(PNR_OK != m_pPlayer->AddAdviseSink(static_cast<IRMAClientAdviseSink*>(this)))
132 return(false);
134 if(PNR_OK != m_pPlayer->SetClientContext((IUnknown*)(INonDelegatingUnknown*)(this)))
135 return(false);
137 // TODO
139 if(CComQIPtr<IRMAPreferences, &IID_IRMAPreferences> pPrefs = m_pPlayer)
141 CComPtr<IRMABuffer> pBuffer;
142 HRESULT hr = pPrefs->ReadPref("HTTPProxyHost", *&pBuffer);
144 UCHAR* pData = NULL;
145 ULONG32 ulLength = 0;
146 hr = pBuffer->Get(pData, ulLength);
148 pBuffer = NULL;
149 hr = m_pCommonClassFactory->CreateInstance(CLSID_IRMABuffer, (void**)&pBuffer);
150 hr = pBuffer->SetSize(strlen("localhost")+1);
151 pData = pBuffer->GetBuffer();
152 strcpy((char*)pData, "localhost");
153 hr = pBuffer->Set(pData, strlen("localhost")+1);
155 pData = NULL;
156 ulLength = 0;
157 hr = pBuffer->Get(pData, ulLength);
159 hr = pPrefs->WritePref("HTTPProxyHost", pBuffer);
161 hr = hr;
164 return(true);
167 void CRealMediaPlayer::Deinit()
169 if(m_pPlayer)
171 m_pPlayer->Stop();
173 CComQIPtr<IRMAErrorSinkControl, &IID_IRMAErrorSinkControl> pErrorSinkControl = m_pPlayer;
174 if(pErrorSinkControl) pErrorSinkControl->RemoveErrorSink(static_cast<IRMAErrorSink*>(this));
176 m_pPlayer->RemoveAdviseSink(static_cast<IRMAClientAdviseSink*>(this));
178 m_pVolume = NULL;
179 m_pAudioPlayer->RemovePostMixHook(static_cast<IRMAAudioHook*>(this));
180 m_pAudioPlayer.Release();
182 m_pEngine->ClosePlayer(m_pPlayer);
184 m_pSiteManager.Release();
185 m_pCommonClassFactory.Release();
187 m_pPlayer = NULL;
190 if(m_pEngine)
192 m_fpCloseEngine(m_pEngine);
193 m_pEngine = NULL;
196 if(m_hRealMediaCore)
198 FreeLibrary(m_hRealMediaCore);
199 m_hRealMediaCore = NULL;
203 STDMETHODIMP CRealMediaPlayer::NonDelegatingQueryInterface(REFIID riid, void** ppv)
205 CheckPointer(ppv, E_POINTER);
207 return
208 QI2(IRMAErrorSink)
209 QI2(IRMAClientAdviseSink)
210 QI2(IRMAAuthenticationManager)
211 QI2(IRMASiteSupplier)
212 QI2(IRMAPassiveSiteWatcher)
213 QI2(IRMAAudioHook)
214 __super::NonDelegatingQueryInterface(riid, ppv);
217 // IRMAErrorSink
218 STDMETHODIMP CRealMediaPlayer::ErrorOccurred(const UINT8 unSeverity, const UINT32 ulRMACode, const UINT32 ulUserCode, const char* pUserString, const char* pMoreInfoURL)
220 char* errmsg = NULL;
222 if(unSeverity < 5)
224 if(CComQIPtr<IRMAErrorMessages, &IID_IRMAErrorMessages> pErrorMessages = m_pPlayer)
226 CComPtr<IRMABuffer> pBuffer = pErrorMessages->GetErrorText(ulRMACode);
227 if(pBuffer)
229 char* buff = (char*)pBuffer->GetBuffer();
230 int len = strlen(buff);
231 if(len > 0 && (errmsg = (char*)CoTaskMemAlloc(len+1)))
232 strcpy(errmsg, buff);
236 if(!errmsg && (errmsg = (char*)CoTaskMemAlloc(strlen("RealMedia error")+1)))
237 strcpy(errmsg, "RealMedia error");
239 m_pRMG->NotifyEvent(EC_BG_ERROR, (LONG_PTR)errmsg, 0);
242 return PNR_OK;
245 // IRMAClientAdviseSink
246 STDMETHODIMP CRealMediaPlayer::OnPosLength(UINT32 ulPosition, UINT32 ulLength)
248 m_nCurrent = (REFERENCE_TIME)ulPosition*10000;
249 m_nDuration = (REFERENCE_TIME)ulLength*10000;
250 return PNR_OK;
252 STDMETHODIMP CRealMediaPlayer::OnPresentationOpened() {return PNR_OK;}
253 STDMETHODIMP CRealMediaPlayer::OnPresentationClosed() {return PNR_OK;}
254 STDMETHODIMP CRealMediaPlayer::OnStatisticsChanged()
256 m_pRMG->NotifyEvent(EC_LENGTH_CHANGED);
257 return PNR_OK;
259 STDMETHODIMP CRealMediaPlayer::OnPreSeek(UINT32 ulOldTime, UINT32 ulNewTime)
261 m_nCurrent = (REFERENCE_TIME)ulNewTime*10000;
262 return PNR_OK;
264 STDMETHODIMP CRealMediaPlayer::OnPostSeek(UINT32 ulOldTime, UINT32 ulNewTime)
266 m_nCurrent = (REFERENCE_TIME)ulNewTime*10000;
267 return PNR_OK;
269 STDMETHODIMP CRealMediaPlayer::OnStop()
271 m_nCurrent = 0;
272 m_State = State_Stopped;
273 if(m_UserState != State_Stopped)
274 m_pRMG->NotifyEvent(EC_COMPLETE);
275 return PNR_OK;
277 STDMETHODIMP CRealMediaPlayer::OnPause(UINT32 ulTime)
279 m_State = State_Paused;
280 return PNR_OK;
282 STDMETHODIMP CRealMediaPlayer::OnBegin(UINT32 ulTime)
284 m_State = State_Running;
285 return PNR_OK;
287 STDMETHODIMP CRealMediaPlayer::OnBuffering(UINT32 ulFlags, UINT16 unPercentComplete)
289 m_unPercentComplete = unPercentComplete;
290 return PNR_OK;
292 STDMETHODIMP CRealMediaPlayer::OnContacting(const char* pHostName) {return PNR_OK;}
294 // IRMAAuthenticationManager
295 STDMETHODIMP CRealMediaPlayer::HandleAuthenticationRequest(IRMAAuthenticationManagerResponse* pResponse)
297 CAuthDlg dlg;
299 if(dlg.DoModal() == IDOK)
301 pResponse->AuthenticationRequestDone(
302 PNR_OK, CStringA(dlg.m_username), CStringA(dlg.m_password));
303 return PNR_OK;
306 return pResponse->AuthenticationRequestDone(PNR_NOT_AUTHORIZED, NULL, NULL);
309 // IRMASiteSupplier
310 STDMETHODIMP CRealMediaPlayer::SitesNeeded(UINT32 uRequestID, IRMAValues* pProps)
312 if(!pProps) return PNR_INVALID_PARAMETER;
314 if(m_pTheSite || m_pTheSite2 || !m_hWndParent) return PNR_UNEXPECTED;
316 HRESULT hr = PNR_OK;
318 if(!CreateSite(&m_pTheSite))
319 return E_FAIL;
321 ULONG refc = ((IRMASite*)m_pTheSite)->AddRef();
322 refc = ((IRMASite*)m_pTheSite)->Release();
324 if(!(m_pTheSite2 = m_pTheSite))
325 return E_NOINTERFACE;
327 CComQIPtr<IRMAValues, &IID_IRMAValues> pSiteProps = m_pTheSite;
328 if(!pSiteProps)
329 return E_NOINTERFACE;
331 IRMABuffer* pValue;
333 // no idea what these supposed to do... but they were in the example
334 hr = pProps->GetPropertyCString("playto", pValue);
335 if(PNR_OK == hr)
337 pSiteProps->SetPropertyCString("channel", pValue);
338 pValue->Release();
340 else
342 hr = pProps->GetPropertyCString("name", pValue);
343 if(PNR_OK == hr)
345 pSiteProps->SetPropertyCString("LayoutGroup", pValue);
346 pValue->Release();
350 m_pTheSite2->AddPassiveSiteWatcher(static_cast<IRMAPassiveSiteWatcher*>(this));
352 hr = m_pSiteManager->AddSite(m_pTheSite);
353 if(PNR_OK != hr)
354 return hr;
356 m_CreatedSites[uRequestID] = m_pTheSite;
358 return hr;
361 STDMETHODIMP CRealMediaPlayer::SitesNotNeeded(UINT32 uRequestID)
363 IRMASite* pSite;
364 if(!m_CreatedSites.Lookup(uRequestID, pSite))
365 return PNR_INVALID_PARAMETER;
367 m_CreatedSites.RemoveKey(uRequestID);
369 m_pSiteManager->RemoveSite(pSite);
371 m_pTheSite2->RemovePassiveSiteWatcher(static_cast<IRMAPassiveSiteWatcher*>(this));
373 m_pTheSite.Release();
374 m_pTheSite2.Release();
376 DestroySite(pSite);
378 return PNR_OK;
380 STDMETHODIMP CRealMediaPlayer::BeginChangeLayout() {return E_NOTIMPL;}
381 STDMETHODIMP CRealMediaPlayer::DoneChangeLayout()
383 if(m_fVideoSizeChanged)
385 m_pRMG->NotifyEvent(EC_VIDEO_SIZE_CHANGED, MAKELPARAM(m_VideoSize.cx, m_VideoSize.cy), 0);
386 m_fVideoSizeChanged = false;
389 return PNR_OK;
392 // IRMAPassiveSiteWatcher
393 STDMETHODIMP CRealMediaPlayer::PositionChanged(PNxPoint* pos) {return E_NOTIMPL;}
394 STDMETHODIMP CRealMediaPlayer::SizeChanged(PNxSize* size)
396 if(m_VideoSize.cx == 0 || m_VideoSize.cy == 0)
398 m_fVideoSizeChanged = true;
399 m_VideoSize.cx = size->cx;
400 m_VideoSize.cy = size->cy;
402 return PNR_OK;
405 // IRMAAudioHook
406 STDMETHODIMP CRealMediaPlayer::OnBuffer(RMAAudioData* pAudioInData, RMAAudioData* pAudioOutData) {return E_NOTIMPL;}
407 STDMETHODIMP CRealMediaPlayer::OnInit(RMAAudioFormat* pFormat)
409 m_pRMG->NotifyEvent(EC_BG_AUDIO_CHANGED, pFormat->uChannels, 0);
410 return PNR_OK;
414 // CRealMediaPlayerWindowed
417 CRealMediaPlayerWindowed::CRealMediaPlayerWindowed(HWND hWndParent, CRealMediaGraph* pRMG)
418 : CRealMediaPlayer(hWndParent, pRMG)
420 if(!m_wndWindowFrame.CreateEx(WS_EX_NOPARENTNOTIFY, NULL, NULL, WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_VISIBLE,
421 CRect(0, 0, 0, 0), CWnd::FromHandle(m_hWndParent), 0, NULL))
422 return;
424 if(!m_wndDestFrame.Create(NULL, NULL, WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN,
425 CRect(0, 0, 0, 0), &m_wndWindowFrame, 0, NULL))
426 return;
429 CRealMediaPlayerWindowed::~CRealMediaPlayerWindowed()
431 m_wndDestFrame.DestroyWindow();
432 m_wndWindowFrame.DestroyWindow();
435 void CRealMediaPlayerWindowed::SetWindowRect(CRect r)
437 if(IsWindow(m_wndWindowFrame.m_hWnd))
438 m_wndWindowFrame.MoveWindow(r);
441 void CRealMediaPlayerWindowed::SetDestRect(CRect r)
443 if(IsWindow(m_wndDestFrame.m_hWnd))
444 m_wndDestFrame.MoveWindow(r);
446 if(m_pTheSite)
448 PNxSize s = {r.Width(), r.Height()};
449 m_pTheSite->SetSize(s);
453 bool CRealMediaPlayerWindowed::CreateSite(IRMASite** ppSite)
455 if(!ppSite)
456 return(false);
458 CComPtr<IRMASiteWindowed> pSiteWindowed;
459 if(PNR_OK != m_pCommonClassFactory->CreateInstance(CLSID_IRMASiteWindowed, (void**)&pSiteWindowed))
460 return(false);
462 DWORD style = WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN;
463 if(!AfxGetAppSettings().fIntRealMedia) style |= WS_DISABLED;
464 if(PNR_OK != pSiteWindowed->Create(m_wndDestFrame.m_hWnd, style))
465 return(false);
467 return !!(*ppSite = CComQIPtr<IRMASite, &IID_IRMASite>(pSiteWindowed).Detach());
470 void CRealMediaPlayerWindowed::DestroySite(IRMASite* pSite)
472 if(CComQIPtr<IRMASiteWindowed, &IID_IRMASiteWindowed> pRMASiteWindowed = pSite)
473 pRMASiteWindowed->Destroy();
476 // CRealMediaPlayerWindowless
479 CRealMediaPlayerWindowless::CRealMediaPlayerWindowless(HWND hWndParent, CRealMediaGraph* pRMG)
480 : CRealMediaPlayer(hWndParent, pRMG)
482 AppSettings& s = AfxGetAppSettings();
484 switch(s.iRMVideoRendererType)
486 default:
487 case VIDRNDT_RM_DX7:
488 if(FAILED(CreateAP7(CLSID_RM7AllocatorPresenter, hWndParent, &m_pRMAP)))
489 return;
490 break;
491 case VIDRNDT_RM_DX9:
492 if(FAILED(CreateAP9(CLSID_RM9AllocatorPresenter, hWndParent, &m_pRMAP)))
493 return;
494 break;
498 CRealMediaPlayerWindowless::~CRealMediaPlayerWindowless()
502 STDMETHODIMP CRealMediaPlayerWindowless::NonDelegatingQueryInterface(REFIID riid, void** ppv)
504 CheckPointer(ppv, E_POINTER);
506 return
507 (m_pRMAP && (riid == __uuidof(ISubPicAllocatorPresenter) || riid == IID_IRMAVideoSurface)) ? m_pRMAP->QueryInterface(riid, ppv) :
508 __super::NonDelegatingQueryInterface(riid, ppv);
511 bool CRealMediaPlayerWindowless::CreateSite(IRMASite** ppSite)
513 if(!ppSite || !m_pRMAP)
514 return(false);
516 HRESULT hr = S_OK;
518 CRealMediaWindowlessSite* pWMWlS;
520 CComPtr<IRMASiteWindowless> pSiteWindowless;
521 pSiteWindowless = (IRMASiteWindowless*)(pWMWlS = new CRealMediaWindowlessSite(hr, m_pPlayer, NULL, NULL));
522 if(FAILED(hr))
523 return(false);
525 pWMWlS->SetBltService(CComQIPtr<IRMAVideoSurface, &IID_IRMAVideoSurface>(m_pRMAP));
527 return !!(*ppSite = CComQIPtr<IRMASite, &IID_IRMASite>(pSiteWindowless).Detach());
530 void CRealMediaPlayerWindowless::DestroySite(IRMASite* pSite)
534 STDMETHODIMP CRealMediaPlayerWindowless::SizeChanged(PNxSize* size)
536 if(CComQIPtr<IRMAVideoSurface, &IID_IRMAVideoSurface> pRMAVS = m_pRMAP)
538 RMABitmapInfoHeader BitmapInfo;
539 memset(&BitmapInfo, 0, sizeof(BitmapInfo));
540 BitmapInfo.biWidth = size->cx;
541 BitmapInfo.biHeight = size->cy;
542 pRMAVS->BeginOptimizedBlt(&BitmapInfo);
545 return __super::SizeChanged(size);
549 ////////////////
551 CRealMediaGraph::CRealMediaGraph(HWND hWndParent, HRESULT& hr)
552 : CBaseGraph()
554 hr = S_OK;
556 m_pRMP = AfxGetAppSettings().iRMVideoRendererType == VIDRNDT_RM_DEFAULT
557 ? (CRealMediaPlayer*)new CRealMediaPlayerWindowed(hWndParent, this)
558 : (CRealMediaPlayer*)new CRealMediaPlayerWindowless(hWndParent, this);
560 if(!m_pRMP)
562 hr = E_OUTOFMEMORY;
563 return;
566 if(!m_pRMP->Init())
568 delete m_pRMP, m_pRMP = NULL;
569 hr = E_FAIL;
570 return;
573 m_pRMP->AddRef();
576 CRealMediaGraph::~CRealMediaGraph()
578 if(m_pRMP)
580 m_pRMP->Deinit();
581 m_pRMP->Release();
582 m_pRMP = NULL;
586 STDMETHODIMP CRealMediaGraph::NonDelegatingQueryInterface(REFIID riid, void** ppv)
588 CheckPointer(ppv, E_POINTER);
590 return
591 (m_pRMP && (riid == __uuidof(ISubPicAllocatorPresenter) || riid == __uuidof(ISubPicAllocatorPresenter))) ? m_pRMP->QueryInterface(riid, ppv) :
592 __super::NonDelegatingQueryInterface(riid, ppv);
595 // IGraphBuilder
596 STDMETHODIMP CRealMediaGraph::RenderFile(LPCWSTR lpcwstrFile, LPCWSTR lpcwstrPlayList)
598 m_fn = lpcwstrFile;
600 CHAR buff[MAX_PATH] = {0};
601 WideCharToMultiByte(GetACP(), 0, lpcwstrFile, -1, buff, MAX_PATH, 0, 0);
603 CStringA fn(buff);
604 if(fn.Find("://") < 0) fn = "file://" + fn;
606 m_pRMP->m_unPercentComplete = 100;
608 ClearMessageQueue();
610 if(PNR_OK != m_pRMP->m_pPlayer->OpenURL(fn))
611 return E_FAIL;
613 m_pRMP->m_pPlayer->Pause()/*Stop()*/; // please, don't start just yet
615 return S_OK;
618 // IMediaControl
619 STDMETHODIMP CRealMediaGraph::Run()
621 if(m_pRMP->m_pPlayer->IsDone())
622 RenderFile(m_fn, NULL);
624 m_pRMP->m_UserState = State_Running;
625 return (PNR_OK == m_pRMP->m_pPlayer->Begin()) ? S_OK : E_FAIL;
627 STDMETHODIMP CRealMediaGraph::Pause()
629 m_pRMP->m_UserState = State_Paused;
630 return (PNR_OK == m_pRMP->m_pPlayer->Pause()) ? S_OK : E_FAIL;
632 STDMETHODIMP CRealMediaGraph::Stop()
634 m_pRMP->m_UserState = State_Stopped;
635 return (PNR_OK == m_pRMP->m_pPlayer->Stop()) ? S_OK : E_FAIL;
637 STDMETHODIMP CRealMediaGraph::GetState(LONG msTimeout, OAFilterState* pfs)
639 return pfs ? *pfs = m_pRMP->m_State, S_OK : E_POINTER;
642 // IMediaSeeking
643 STDMETHODIMP CRealMediaGraph::GetDuration(LONGLONG* pDuration)
645 return pDuration ? *pDuration = m_pRMP->m_nDuration, S_OK : E_POINTER;
647 STDMETHODIMP CRealMediaGraph::GetCurrentPosition(LONGLONG* pCurrent)
649 return pCurrent ? *pCurrent = m_pRMP->m_nCurrent, S_OK : E_POINTER;
651 STDMETHODIMP CRealMediaGraph::SetPositions(LONGLONG* pCurrent, DWORD dwCurrentFlags, LONGLONG* pStop, DWORD dwStopFlags)
653 return (dwCurrentFlags&AM_SEEKING_AbsolutePositioning)
654 && (PNR_OK == m_pRMP->m_pPlayer->Seek((ULONG)(*pCurrent / 10000))) ? S_OK : E_FAIL;
657 // IVideoWindow
658 STDMETHODIMP CRealMediaGraph::SetWindowPosition(long Left, long Top, long Width, long Height)
660 if(m_pRMP)
661 m_pRMP->SetWindowRect(CRect(CPoint(Left, Top), CSize(Width, Height)));
663 return S_OK;
666 // IBasicVideo
667 STDMETHODIMP CRealMediaGraph::SetDestinationPosition(long Left, long Top, long Width, long Height)// {return E_NOTIMPL;}
669 m_pRMP->SetDestRect(CRect(CPoint(Left, Top), CSize(Width, Height)));
670 return S_OK;
672 STDMETHODIMP CRealMediaGraph::GetVideoSize(long* pWidth, long* pHeight)
674 if(!pWidth || !pHeight) return E_POINTER;
675 *pWidth = m_pRMP->GetVideoSize().cx;
676 *pHeight = m_pRMP->GetVideoSize().cy;
677 return S_OK;
680 // IBasicAudio
681 STDMETHODIMP CRealMediaGraph::put_Volume(long lVolume)
683 if(!m_pRMP->m_pVolume) return E_UNEXPECTED;
685 UINT16 volume = (lVolume == -10000) ? 0 : (int)pow(10.0, ((double)lVolume)/5000+2);
686 volume = max(min(volume, 100), 0);
688 return PNR_OK == m_pRMP->m_pVolume->SetVolume(volume) ? S_OK : E_FAIL;
690 STDMETHODIMP CRealMediaGraph::get_Volume(long* plVolume)
692 if(!m_pRMP->m_pVolume) return E_UNEXPECTED;
694 CheckPointer(plVolume, E_POINTER);
696 UINT16 volume = m_pRMP->m_pVolume->GetVolume();
697 volume = (int)((log10(1.0*volume)-2)*5000);
698 volume = max(min(volume, 0), -10000);
700 *plVolume = volume;
702 return S_OK;
705 // IAMOpenProgress
706 STDMETHODIMP CRealMediaGraph::QueryProgress(LONGLONG* pllTotal, LONGLONG* pllCurrent)
708 *pllTotal = 100;
709 *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
710 return S_OK;
713 // IGraphEngine
714 STDMETHODIMP_(engine_t) CRealMediaGraph::GetEngine() {return RealMedia;}