Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1979 lines
47 KiB

  1. // MediaBarPlayer.cpp
  2. #include "priv.h"
  3. #include "dispex.h"
  4. #include "player.h"
  5. #include "resource.h"
  6. #include "math.h"
  7. #include "mediautil.h"
  8. #include "mbBehave.h"
  9. #define WZ_PLAY L"beginElement"
  10. #define WZ_STOP L"endElement"
  11. #define WZ_PAUSE L"pauseElement"
  12. #define WZ_RESUME L"resumeElement"
  13. #define WZ_URL L"src"
  14. #define WZ_VOLUME L"volume"
  15. #define WZ_MUTE L"mute"
  16. #define WZ_REGISTERED_TIME_NAME L"HTMLTIME"
  17. #define WZ_BODY L"body"
  18. #define WZ_PLAYER L"player"
  19. #define WZ_ONMEDIACOMPLETE L"onmediacomplete"
  20. #define WZ_MEDIACOMPLETE L"mediacomplete"
  21. #define WZ_ONMEDIAERROR L"onmediaerror"
  22. #define WZ_MEDIAERROR L"mediaerror"
  23. #define WZ_ONTRACKCHANGE L"ontrackchange"
  24. #define WZ_TRACKCHANGE L"trackchange"
  25. #define WZ_ONEND L"onend"
  26. #define WZ_END L"end"
  27. #define WZ_PARAM L"Param"
  28. /////////////////////// Convenience macros ////////////////////
  29. //
  30. // used in QI calls,
  31. // e.g. IOleSite * pSite; p->QI( IID_TO_PPV(IOleInPlaceSite, &pSite) )
  32. // would cause a C2440 as _src is not really a _type **.
  33. // Note: the riid must be the _type prepended by IID_.
  34. //
  35. #define IID_TO_PPV(_type,_src) IID_##_type, \
  36. reinterpret_cast<void **>(static_cast<_type **>(_src))
  37. // Explicit directive to ignore a return value
  38. #define IGNORE_RETURN(_call) static_cast<void>((_call))
  39. #define ERROREXIT(hr) if(FAILED(hr)){hr = E_FAIL; goto done;}
  40. #define IGNORE_HR(hr) IGNORE_RETURN(hr)
  41. #define TIME_INFINITE HUGE_VAL
  42. static inline double
  43. Clamp(double min, double val, double max)
  44. {
  45. if (val < min)
  46. {
  47. val = min;
  48. }
  49. else if (val > max)
  50. {
  51. val = max;
  52. }
  53. return val;
  54. }
  55. /****************************************************\
  56. FUNCTION: CMediaBarPlayer_CreateInstance
  57. DESCRIPTION:
  58. This function will create an instance of the
  59. MediaBarPlayer COM object.
  60. \****************************************************/
  61. HRESULT CMediaBarPlayer_CreateInstance(REFIID riid, void ** ppvObj)
  62. {
  63. // aggregation checking is handled in class factory
  64. CComObject<CMediaBarPlayer> * pMediaBarPlayer = NULL;
  65. *ppvObj = NULL;
  66. HRESULT hr = CComObject<CMediaBarPlayer>::CreateInstance(&pMediaBarPlayer);
  67. if (FAILED(hr))
  68. return hr;
  69. hr = pMediaBarPlayer->QueryInterface(riid, ppvObj);
  70. if (FAILED(hr))
  71. delete pMediaBarPlayer;
  72. return hr;
  73. }
  74. //+-------------------------------------------------------------------------
  75. // Constructor
  76. //--------------------------------------------------------------------------
  77. CMediaBarPlayer::CMediaBarPlayer() :
  78. _dwDocumentEventConPtCookie(0),
  79. _dwCookiePropNotify(0),
  80. _pMediaBar(NULL),
  81. _hwnd(NULL)
  82. {
  83. }
  84. //+-------------------------------------------------------------------------
  85. // Destructor
  86. //--------------------------------------------------------------------------
  87. CMediaBarPlayer::~CMediaBarPlayer()
  88. {
  89. _DestroyHost();
  90. }
  91. //+-------------------------------------------------------------------------
  92. // Creates the control host
  93. //--------------------------------------------------------------------------
  94. STDMETHODIMP
  95. CMediaBarPlayer::_CreateHost(HWND hWnd)
  96. {
  97. HRESULT hr = E_FAIL;
  98. if (_spBrowser.p)
  99. {
  100. hr = E_FAIL;
  101. goto done;
  102. }
  103. if (hWnd && ::IsWindow(hWnd) && _pMediaBar)
  104. {
  105. // Register the OCHost window class
  106. SHDRC shdrc = {sizeof(SHDRC), SHDRCF_OCHOST};
  107. shdrc.cbSize = sizeof (SHDRC);
  108. shdrc.dwFlags |= SHDRCF_OCHOST;
  109. if (DllRegisterWindowClasses(&shdrc))
  110. {
  111. // Create an OCHost window
  112. _hwnd = CreateWindow(OCHOST_CLASS, NULL,
  113. (WS_CHILD|WS_CLIPCHILDREN|WS_CLIPSIBLINGS) & ~(WS_HSCROLL|WS_VSCROLL),
  114. 0, 0, 0, 0,
  115. hWnd, NULL, HINST_THISDLL, NULL);
  116. if (_hwnd)
  117. {
  118. OCHINITSTRUCT ocs;
  119. ocs.cbSize = SIZEOF(OCHINITSTRUCT);
  120. ocs.clsidOC = CLSID_WebBrowser;
  121. ocs.punkOwner = SAFECAST(_pMediaBar, IUnknown*);
  122. hr = OCHost_InitOC(_hwnd, (LPARAM)&ocs);
  123. ERROREXIT(hr)
  124. OCHost_QueryInterface(_hwnd, IID_PPV_ARG(IWebBrowser2, &_spBrowser));
  125. OCHost_DoVerb(_hwnd, OLEIVERB_INPLACEACTIVATE, FALSE);
  126. }
  127. }
  128. }
  129. if (!_spBrowser.p)
  130. {
  131. hr = E_FAIL;
  132. goto done;
  133. }
  134. // navigate to the page containing the player
  135. {
  136. TCHAR szModule[_MAX_PATH];
  137. GetModuleFileName(_Module.GetModuleInstance(), szModule, _MAX_PATH);
  138. // generate the url for the HTML resource containing the player
  139. CComBSTR sbstrURL(OLESTR("res://"));
  140. sbstrURL.Append(szModule);
  141. sbstrURL.Append(OLESTR("/"));
  142. TCHAR szResID[11];
  143. wnsprintf(szResID, _MAX_PATH, _T("%d"), IDH_PLAYER);
  144. sbstrURL.Append(szResID);
  145. hr = _Navigate(sbstrURL.m_str);
  146. ERROREXIT(hr)
  147. }
  148. // listen to events
  149. hr = _InitEventSink();
  150. ERROREXIT(hr)
  151. hr = S_OK;
  152. done:
  153. if (FAILED(hr))
  154. {
  155. _DestroyHost();
  156. }
  157. return hr;
  158. }
  159. STDMETHODIMP
  160. CMediaBarPlayer::_Navigate(BSTR bstrUrl)
  161. {
  162. HRESULT hr = E_FAIL;
  163. CComVariant svarEmpty;
  164. if (!bstrUrl || !_spBrowser.p)
  165. {
  166. hr = E_FAIL;
  167. goto done;
  168. }
  169. hr = _spBrowser->Navigate(bstrUrl, &svarEmpty, &svarEmpty, &svarEmpty, &svarEmpty);
  170. ERROREXIT(hr)
  171. hr = S_OK;
  172. done:
  173. return hr;
  174. }
  175. //+-------------------------------------------------------------------------
  176. // Destroys the control host
  177. //--------------------------------------------------------------------------
  178. STDMETHODIMP
  179. CMediaBarPlayer::_DestroyHost()
  180. {
  181. _AttachPlayerEvents(FALSE);
  182. _UnhookPropNotifies();
  183. _DeInitEventSink();
  184. if (_spMediaElem.p)
  185. {
  186. _spMediaElem.Release();
  187. }
  188. if (_spMediaElem2.p)
  189. {
  190. _spMediaElem2.Release();
  191. }
  192. if (_spPlayerHTMLElem2.p)
  193. {
  194. _spPlayerHTMLElem2.Release();
  195. }
  196. if (_spBodyElem.p)
  197. {
  198. _spBodyElem.Release();
  199. }
  200. if (_spBrowser.p)
  201. {
  202. _spBrowser.Release();
  203. }
  204. if (_hwnd && ::IsWindow(_hwnd))
  205. {
  206. ::DestroyWindow(_hwnd);
  207. _hwnd = NULL;
  208. }
  209. return S_OK;
  210. }
  211. STDMETHODIMP
  212. CMediaBarPlayer::GetVideoHwnd(HWND * pHwnd)
  213. {
  214. if (pHwnd)
  215. *pHwnd = _hwnd;
  216. return S_OK;
  217. }
  218. static const PWSTR ppszInterestingEvents[] =
  219. {
  220. WZ_ONMEDIACOMPLETE,
  221. WZ_ONMEDIAERROR,
  222. WZ_ONEND,
  223. WZ_ONTRACKCHANGE
  224. };
  225. //+-------------------------------------------------------------------------
  226. // Attaches to player events
  227. //--------------------------------------------------------------------------
  228. STDMETHODIMP
  229. CMediaBarPlayer::_AttachPlayerEvents(BOOL fAttach)
  230. {
  231. HRESULT hr = E_FAIL;
  232. CComPtr<IDispatchEx> spDispEx;
  233. CComPtr<IHTMLElement2> spElem2;
  234. hr = _GetElementDispatch(WZ_PLAYER, &spDispEx);
  235. ERROREXIT(hr)
  236. hr = spDispEx->QueryInterface(IID_TO_PPV(IHTMLElement2, &spElem2));
  237. ERROREXIT(hr)
  238. hr = S_OK;
  239. for (DWORD i = 0; i < ARRAYSIZE(ppszInterestingEvents); i++)
  240. {
  241. if (fAttach)
  242. {
  243. VARIANT_BOOL bSuccess = FALSE;
  244. // Try to attach all events. We don't care if they fail
  245. if (FAILED(spElem2->attachEvent(ppszInterestingEvents[i], static_cast<IDispatch*>(this), &bSuccess)))
  246. {
  247. hr = S_FALSE;
  248. }
  249. }
  250. else
  251. {
  252. // Try to detact all events. We don't care if they fail
  253. hr = spElem2->detachEvent(ppszInterestingEvents[i], static_cast<IDispatch*>(this));
  254. }
  255. }
  256. done:
  257. return hr;
  258. }
  259. //+-------------------------------------------------------------------------
  260. // Hooks property change notifications
  261. //--------------------------------------------------------------------------
  262. STDMETHODIMP
  263. CMediaBarPlayer::_HookPropNotifies()
  264. {
  265. HRESULT hr = E_FAIL;
  266. CComPtr<ITIMEState> spTimeState;
  267. CComPtr<IConnectionPointContainer> spConPtCont;
  268. if (!_spMediaElem || _spPropNotifyCP.p || _dwCookiePropNotify)
  269. {
  270. hr = E_FAIL;
  271. goto done;
  272. }
  273. hr = _spMediaElem->get_currTimeState(&spTimeState);
  274. ERROREXIT(hr)
  275. hr = spTimeState->QueryInterface(IID_TO_PPV(IConnectionPointContainer, &spConPtCont));
  276. ERROREXIT(hr)
  277. hr = spConPtCont->FindConnectionPoint(IID_IPropertyNotifySink, &_spPropNotifyCP);
  278. ERROREXIT(hr)
  279. hr = _spPropNotifyCP->Advise(static_cast<IUnknown*>(static_cast<IDispatch*>(this)), &_dwCookiePropNotify);
  280. ERROREXIT(hr)
  281. hr = S_OK;
  282. done:
  283. return hr;
  284. }
  285. //+-------------------------------------------------------------------------
  286. // Unhooks property change notifications
  287. //--------------------------------------------------------------------------
  288. STDMETHODIMP
  289. CMediaBarPlayer::_UnhookPropNotifies()
  290. {
  291. if (_spPropNotifyCP.p)
  292. {
  293. if (_dwCookiePropNotify != 0)
  294. {
  295. IGNORE_HR(_spPropNotifyCP->Unadvise(_dwCookiePropNotify));
  296. }
  297. _spPropNotifyCP.Release();
  298. }
  299. _dwCookiePropNotify = 0;
  300. return S_OK;
  301. }
  302. //+-------------------------------------------------------------------------
  303. // Invokes a method on the given element
  304. //--------------------------------------------------------------------------
  305. STDMETHODIMP
  306. CMediaBarPlayer::_InvokeDocument(LPWSTR pstrElem, INVOKETYPE it, LPWSTR pstrName, VARIANT * pvarArg)
  307. {
  308. HRESULT hr = E_FAIL;
  309. DISPPARAMS dispparams = {NULL, NULL, 0, 0};
  310. CComPtr<IDispatchEx> spDispEx;
  311. CComBSTR sbstrName;
  312. DISPID dispid = 0;
  313. DISPID dispidProp = 0;
  314. sbstrName.m_str = SysAllocString(pstrName);
  315. if (!sbstrName.m_str)
  316. {
  317. hr = E_OUTOFMEMORY;
  318. goto done;
  319. }
  320. hr = _GetElementDispatch(pstrElem, &spDispEx);
  321. ERROREXIT(hr)
  322. hr = spDispEx->GetDispID(sbstrName, fdexNameEnsure, &dispid);
  323. ERROREXIT(hr)
  324. switch (it)
  325. {
  326. case IT_METHOD:
  327. {
  328. dispparams.rgvarg = pvarArg;
  329. dispparams.cArgs = (pvarArg ? 1 : 0);
  330. hr = spDispEx->InvokeEx(dispid, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
  331. ERROREXIT(hr)
  332. }
  333. break;
  334. case IT_PUT:
  335. {
  336. dispidProp = DISPID_PROPERTYPUT;
  337. if (!pvarArg)
  338. {
  339. hr = E_INVALIDARG;
  340. goto done;
  341. }
  342. dispparams.rgvarg = pvarArg;
  343. dispparams.rgdispidNamedArgs = &dispidProp;
  344. dispparams.cArgs = 1;
  345. dispparams.cNamedArgs = 1;
  346. hr = spDispEx->InvokeEx(dispid, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
  347. ERROREXIT(hr)
  348. }
  349. break;
  350. case IT_GET:
  351. {
  352. if (!pvarArg)
  353. {
  354. hr = E_INVALIDARG;
  355. goto done;
  356. }
  357. hr = spDispEx->InvokeEx(dispid, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &dispparams, pvarArg, NULL, NULL);
  358. ERROREXIT(hr)
  359. }
  360. break;
  361. }
  362. hr = S_OK;
  363. done:
  364. return hr;
  365. }
  366. //+-------------------------------------------------------------------------
  367. // Gets the dispatch ptr of the document
  368. //--------------------------------------------------------------------------
  369. STDMETHODIMP
  370. CMediaBarPlayer::_GetDocumentDispatch(IDispatch ** ppDocDisp)
  371. {
  372. HRESULT hr = E_FAIL;
  373. if (!ppDocDisp)
  374. {
  375. hr = E_INVALIDARG;
  376. goto done;
  377. }
  378. if (!_spBrowser)
  379. {
  380. hr = E_FAIL;
  381. goto done;
  382. }
  383. hr = _spBrowser->get_Document(ppDocDisp);
  384. ERROREXIT(hr)
  385. hr = S_OK;
  386. done:
  387. return hr;
  388. }
  389. //+-------------------------------------------------------------------------
  390. // Gets the ITIMEBodyElement interface
  391. //--------------------------------------------------------------------------
  392. STDMETHODIMP
  393. CMediaBarPlayer::_GetBodyElement(ITIMEBodyElement ** ppBodyElem)
  394. {
  395. HRESULT hr = E_FAIL;
  396. CComVariant svarArg;
  397. if (!ppBodyElem)
  398. {
  399. hr = E_INVALIDARG;
  400. goto done;
  401. }
  402. hr = _InvokeDocument(WZ_BODY, IT_GET, WZ_REGISTERED_TIME_NAME, &svarArg);
  403. ERROREXIT(hr)
  404. hr = ::VariantChangeType(&svarArg, &svarArg, NULL, VT_DISPATCH);
  405. ERROREXIT(hr)
  406. if (NULL == V_DISPATCH(&svarArg))
  407. {
  408. hr = E_FAIL;
  409. goto done;
  410. }
  411. hr = V_DISPATCH(&svarArg)->QueryInterface(IID_TO_PPV(ITIMEBodyElement, ppBodyElem));
  412. ERROREXIT(hr)
  413. ASSERT(ppBodyElem);
  414. hr = S_OK;
  415. done:
  416. return hr;
  417. }
  418. //+-------------------------------------------------------------------------
  419. // Gets the ITIMEMediaElement interface
  420. //--------------------------------------------------------------------------
  421. STDMETHODIMP
  422. CMediaBarPlayer::_GetMediaElement(ITIMEMediaElement ** ppMediaElem)
  423. {
  424. HRESULT hr = E_FAIL;
  425. CComVariant svarArg;
  426. if (!ppMediaElem)
  427. {
  428. hr = E_INVALIDARG;
  429. goto done;
  430. }
  431. hr = _InvokeDocument(WZ_PLAYER, IT_GET, WZ_REGISTERED_TIME_NAME, &svarArg);
  432. ERROREXIT(hr)
  433. hr = ::VariantChangeType(&svarArg, &svarArg, NULL, VT_DISPATCH);
  434. ERROREXIT(hr)
  435. if (NULL == V_DISPATCH(&svarArg))
  436. {
  437. hr = E_FAIL;
  438. goto done;
  439. }
  440. hr = V_DISPATCH(&svarArg)->QueryInterface(IID_TO_PPV(ITIMEMediaElement, ppMediaElem));
  441. ERROREXIT(hr)
  442. ASSERT(ppMediaElem);
  443. hr = S_OK;
  444. done:
  445. return hr;
  446. }
  447. //+-------------------------------------------------------------------------
  448. // Gets the IDispatchEx pointer of the named element
  449. //--------------------------------------------------------------------------
  450. STDMETHODIMP
  451. CMediaBarPlayer::_GetElementDispatch(LPWSTR pstrElem, IDispatchEx ** ppDispEx)
  452. {
  453. HRESULT hr = E_FAIL;
  454. CComPtr<IDispatch> spElemDisp;
  455. CComPtr<IDispatch> spDocDisp;
  456. CComPtr<IHTMLDocument2> spDoc2;
  457. CComPtr<IHTMLElementCollection> spAll;
  458. CComVariant svarName;
  459. CComVariant svarIndex;
  460. if (!ppDispEx || !pstrElem)
  461. {
  462. hr = E_INVALIDARG;
  463. goto done;
  464. }
  465. V_VT(&svarName) = VT_BSTR;
  466. V_BSTR(&svarName) = SysAllocString(pstrElem);
  467. if (NULL == V_BSTR(&svarName))
  468. {
  469. hr = E_OUTOFMEMORY;
  470. goto done;
  471. }
  472. V_VT(&svarIndex) = VT_I4;
  473. V_I4(&svarIndex) = 0;
  474. hr = _GetDocumentDispatch(&spDocDisp);
  475. ERROREXIT(hr)
  476. // WebOC returns S_OK even if doc disp is not available
  477. if (!spDocDisp.p)
  478. {
  479. hr = E_FAIL;
  480. goto done;
  481. }
  482. hr = spDocDisp->QueryInterface(IID_TO_PPV(IHTMLDocument2, &spDoc2));
  483. ERROREXIT(hr)
  484. hr = spDoc2->get_all(&spAll);
  485. ERROREXIT(hr)
  486. hr = spAll->item(svarName, svarIndex, &spElemDisp);
  487. ERROREXIT(hr)
  488. if (spElemDisp.p)
  489. {
  490. hr = spElemDisp->QueryInterface(IID_TO_PPV(IDispatchEx, ppDispEx));
  491. ERROREXIT(hr)
  492. }
  493. else
  494. {
  495. hr = E_FAIL;
  496. goto done;
  497. }
  498. hr = S_OK;
  499. done:
  500. return hr;
  501. }
  502. //+-------------------------------------------------------------------------
  503. // Stuff to be done when document is loaded
  504. //--------------------------------------------------------------------------
  505. STDMETHODIMP
  506. CMediaBarPlayer::_OnDocumentComplete()
  507. {
  508. HRESULT hr = E_FAIL;
  509. // store off a pointer to the media element behavior
  510. hr = _GetMediaElement(&_spMediaElem);
  511. ERROREXIT(hr)
  512. hr = _spMediaElem->QueryInterface(IID_TO_PPV(ITIMEMediaElement2, &_spMediaElem2));
  513. ERROREXIT(hr)
  514. // store off a pointer to the player's HTML element
  515. {
  516. CComPtr<IDispatchEx> spPlayerDisp;
  517. hr = _GetElementDispatch(WZ_PLAYER, &spPlayerDisp);
  518. ERROREXIT(hr)
  519. if (!spPlayerDisp.p)
  520. {
  521. hr = E_FAIL;
  522. goto done;
  523. }
  524. hr = spPlayerDisp->QueryInterface(IID_TO_PPV(IHTMLElement2, &_spPlayerHTMLElem2));
  525. ERROREXIT(hr)
  526. }
  527. // store off a pointer to the body element
  528. hr = _GetBodyElement(&_spBodyElem);
  529. ERROREXIT(hr)
  530. // Attach to player events
  531. hr = _AttachPlayerEvents(TRUE);
  532. ERROREXIT(hr)
  533. // Hook Property notifications
  534. hr = _HookPropNotifies();
  535. ERROREXIT(hr)
  536. // set the type if deferred
  537. if (_sbstrType.m_str)
  538. {
  539. hr = put_type(_sbstrType);
  540. _sbstrType.Empty();
  541. ERROREXIT(hr)
  542. }
  543. // set the url if deferred
  544. if (_sbstrUrl.m_str)
  545. {
  546. hr = put_url(_sbstrUrl);
  547. _sbstrUrl.Empty();
  548. ERROREXIT(hr)
  549. }
  550. hr = S_OK;
  551. done:
  552. return hr;
  553. }
  554. //+-------------------------------------------------------------------------
  555. // Stuff to be done when Media is ready
  556. //--------------------------------------------------------------------------
  557. STDMETHODIMP
  558. CMediaBarPlayer::_OnMediaComplete()
  559. {
  560. // notify the media bar
  561. if (_pMediaBar)
  562. {
  563. _pMediaBar->Notify(MEDIACOMPLETE);
  564. }
  565. return S_OK;
  566. }
  567. //+-------------------------------------------------------------------------
  568. // Stuff to be done when Media is ready
  569. //--------------------------------------------------------------------------
  570. STDMETHODIMP
  571. CMediaBarPlayer::_OnTrackChange()
  572. {
  573. // notify the media bar
  574. if (_pMediaBar)
  575. {
  576. _pMediaBar->Notify(TRACK_CHANGE);
  577. }
  578. return S_OK;
  579. }
  580. //+-------------------------------------------------------------------------
  581. // Stuff to be done when track is finished
  582. //--------------------------------------------------------------------------
  583. STDMETHODIMP
  584. CMediaBarPlayer::_OnEnd()
  585. {
  586. // notify the media bar
  587. if (_pMediaBar)
  588. {
  589. _pMediaBar->Notify(MEDIA_TRACK_FINISHED);
  590. }
  591. return S_OK;
  592. }
  593. //+-------------------------------------------------------------------------
  594. // notification that there was some error playing the Media stream
  595. //--------------------------------------------------------------------------
  596. STDMETHODIMP
  597. CMediaBarPlayer::_OnMediaError(int iErrCode)
  598. {
  599. CComPtr<IDispatch> spWMP;
  600. if (_spMediaElem && SUCCEEDED(_spMediaElem->get_playerObject(&spWMP)))
  601. {
  602. VARIANT varError;
  603. if (SUCCEEDED(GetProp(spWMP, L"error", &varError)))
  604. {
  605. CallMethod(varError.pdispVal, L"webHelp");
  606. }
  607. VariantClear(&varError);
  608. }
  609. // notify the media bar
  610. if (_pMediaBar)
  611. {
  612. _pMediaBar->OnMediaError(iErrCode);
  613. }
  614. return S_OK;
  615. }
  616. //+-------------------------------------------------------------------------
  617. // Handle property change notifications
  618. //--------------------------------------------------------------------------
  619. STDMETHODIMP
  620. CMediaBarPlayer::OnChanged(DISPID dispid)
  621. {
  622. // notify the media bar
  623. if (_pMediaBar)
  624. {
  625. _pMediaBar->Notify(dispid);
  626. }
  627. return S_OK;
  628. }
  629. ////////////////////////////////////////////////////////////////////////////
  630. //
  631. // IMediaBarPlayer
  632. //
  633. ////////////////////////////////////////////////////////////////////////////
  634. //+-------------------------------------------------------------------------
  635. // Init the player
  636. //--------------------------------------------------------------------------
  637. STDMETHODIMP
  638. CMediaBarPlayer::Init(HWND hWnd, IMediaBar * pMediaBar)
  639. {
  640. HRESULT hr = E_FAIL;
  641. if (!pMediaBar)
  642. {
  643. hr = E_INVALIDARG;
  644. goto done;
  645. }
  646. // store a weak ref to prevent circular reference
  647. _pMediaBar = pMediaBar;
  648. hr = _CreateHost(hWnd);
  649. ERROREXIT(hr)
  650. hr = S_OK;
  651. done:
  652. if (FAILED(hr))
  653. {
  654. DeInit();
  655. }
  656. return hr;
  657. }
  658. //+-------------------------------------------------------------------------
  659. // DeInit the player
  660. //--------------------------------------------------------------------------
  661. STDMETHODIMP
  662. CMediaBarPlayer::DeInit()
  663. {
  664. _pMediaBar = NULL;
  665. return _DestroyHost();
  666. }
  667. //+-------------------------------------------------------------------------
  668. // sets the media clip type
  669. //--------------------------------------------------------------------------
  670. STDMETHODIMP
  671. CMediaBarPlayer::put_type(BSTR bstrType)
  672. {
  673. HRESULT hr = E_FAIL;
  674. CComVariant svarArg;
  675. CComVariant svarEmpty;
  676. svarArg.vt = VT_NULL;
  677. svarEmpty.vt = VT_NULL;
  678. if (!IsReady())
  679. {
  680. _sbstrType.m_str = ::SysAllocString(bstrType);
  681. if (bstrType && !_sbstrType)
  682. {
  683. hr = E_OUTOFMEMORY;
  684. }
  685. else
  686. {
  687. hr = S_OK;
  688. }
  689. goto done;
  690. }
  691. if (bstrType)
  692. {
  693. V_VT(&svarArg) = VT_BSTR;
  694. V_BSTR(&svarArg) = SysAllocString(bstrType);
  695. if (NULL == V_BSTR(&svarArg))
  696. {
  697. hr = E_OUTOFMEMORY;
  698. goto done;
  699. }
  700. }
  701. // always stop the player
  702. hr = _spMediaElem->endElement();
  703. ERROREXIT(hr)
  704. hr = _spMediaElem->put_src(svarEmpty);
  705. ERROREXIT(hr)
  706. hr = _spMediaElem->put_type(svarArg);
  707. ERROREXIT(hr)
  708. hr = S_OK;
  709. done:
  710. return hr;
  711. }
  712. //+-------------------------------------------------------------------------
  713. // sets the media clip url
  714. //--------------------------------------------------------------------------
  715. STDMETHODIMP
  716. CMediaBarPlayer::put_url(BSTR bstrUrl)
  717. {
  718. HRESULT hr = E_FAIL;
  719. CComVariant svarArg;
  720. CComVariant svarEmpty;
  721. svarArg.vt = VT_NULL;
  722. svarEmpty.vt = VT_NULL;
  723. if (!IsReady())
  724. {
  725. _sbstrUrl.m_str = ::SysAllocString(bstrUrl);
  726. if (bstrUrl && !_sbstrUrl)
  727. {
  728. hr = E_OUTOFMEMORY;
  729. }
  730. else
  731. {
  732. hr = S_OK;
  733. }
  734. goto done;
  735. }
  736. if (bstrUrl)
  737. {
  738. V_VT(&svarArg) = VT_BSTR;
  739. V_BSTR(&svarArg) = SysAllocString(bstrUrl);
  740. if (NULL == V_BSTR(&svarArg))
  741. {
  742. hr = E_OUTOFMEMORY;
  743. goto done;
  744. }
  745. }
  746. // always stop the player
  747. hr = _spMediaElem->endElement();
  748. ERROREXIT(hr)
  749. hr = _spMediaElem->put_src(svarArg);
  750. ERROREXIT(hr)
  751. // always start the player
  752. hr = _spMediaElem->beginElement();
  753. ERROREXIT(hr)
  754. hr = S_OK;
  755. done:
  756. return hr;
  757. }
  758. //+-------------------------------------------------------------------------
  759. // gets the media clip url
  760. //--------------------------------------------------------------------------
  761. STDMETHODIMP
  762. CMediaBarPlayer::get_url(BSTR * pbstrUrl)
  763. {
  764. HRESULT hr = E_FAIL;
  765. CComVariant svarArg;
  766. if (!pbstrUrl || !IsReady())
  767. {
  768. hr = E_FAIL;
  769. goto done;
  770. }
  771. *pbstrUrl = NULL;
  772. hr = _spMediaElem->get_src(&svarArg);
  773. ERROREXIT(hr)
  774. hr = svarArg.ChangeType(VT_BSTR);
  775. ERROREXIT(hr)
  776. if (svarArg.bstrVal)
  777. {
  778. *pbstrUrl = SysAllocString(svarArg.bstrVal);
  779. if (NULL == *pbstrUrl)
  780. {
  781. hr = E_OUTOFMEMORY;
  782. goto done;
  783. }
  784. }
  785. hr = S_OK;
  786. done:
  787. return hr;
  788. }
  789. //+-------------------------------------------------------------------------
  790. // gets the player attribute
  791. //--------------------------------------------------------------------------
  792. STDMETHODIMP
  793. CMediaBarPlayer::get_player(BSTR * pbstrPlayer)
  794. {
  795. HRESULT hr = E_FAIL;
  796. CComVariant svarArg;
  797. if (!pbstrPlayer || !IsReady())
  798. {
  799. hr = E_FAIL;
  800. goto done;
  801. }
  802. *pbstrPlayer = NULL;
  803. hr = _spMediaElem->get_player(&svarArg);
  804. ERROREXIT(hr)
  805. hr = svarArg.ChangeType(VT_BSTR);
  806. ERROREXIT(hr)
  807. if (svarArg.bstrVal)
  808. {
  809. *pbstrPlayer = SysAllocString(svarArg.bstrVal);
  810. if (NULL == *pbstrPlayer)
  811. {
  812. hr = E_OUTOFMEMORY;
  813. goto done;
  814. }
  815. }
  816. hr = S_OK;
  817. done:
  818. return hr;
  819. }
  820. //+-------------------------------------------------------------------------
  821. // sets the volume
  822. //--------------------------------------------------------------------------
  823. STDMETHODIMP
  824. CMediaBarPlayer::put_volume(double dblVolume)
  825. {
  826. HRESULT hr = E_FAIL;
  827. CComVariant svarArg;
  828. if (!IsReady())
  829. {
  830. hr = E_FAIL;
  831. goto done;
  832. }
  833. V_VT(&svarArg) = VT_R8;
  834. V_R8(&svarArg) = dblVolume;
  835. hr = _spMediaElem->put_volume(svarArg);
  836. ERROREXIT(hr)
  837. hr = S_OK;
  838. done:
  839. return hr;
  840. }
  841. //+-------------------------------------------------------------------------
  842. // gets the volume
  843. //--------------------------------------------------------------------------
  844. STDMETHODIMP
  845. CMediaBarPlayer::get_volume(double * pdblVolume)
  846. {
  847. return E_NOTIMPL;
  848. }
  849. //+-------------------------------------------------------------------------
  850. // gets the media element pointer
  851. //--------------------------------------------------------------------------
  852. STDMETHODIMP
  853. CMediaBarPlayer::get_mediaElement(ITIMEMediaElement ** ppMediaElem)
  854. {
  855. if (!ppMediaElem || !_spMediaElem)
  856. {
  857. return E_FAIL;
  858. }
  859. *ppMediaElem = _spMediaElem;
  860. (_spMediaElem.p)->AddRef();
  861. return S_OK;
  862. }
  863. //+-------------------------------------------------------------------------
  864. // sets the mute
  865. //--------------------------------------------------------------------------
  866. STDMETHODIMP
  867. CMediaBarPlayer::put_mute(BOOL bMute)
  868. {
  869. HRESULT hr = E_FAIL;
  870. CComVariant svarArg;
  871. if (!IsReady())
  872. {
  873. hr = E_FAIL;
  874. goto done;
  875. }
  876. V_VT(&svarArg) = VT_BOOL;
  877. V_BOOL(&svarArg) = bMute ? VARIANT_TRUE : VARIANT_FALSE;
  878. hr = _spMediaElem->put_mute(svarArg);
  879. ERROREXIT(hr)
  880. hr = S_OK;
  881. done:
  882. return hr;
  883. }
  884. //+-------------------------------------------------------------------------
  885. // gets the mute
  886. //--------------------------------------------------------------------------
  887. STDMETHODIMP
  888. CMediaBarPlayer::get_mute(BOOL * pbMute)
  889. {
  890. return E_NOTIMPL;
  891. }
  892. //+-------------------------------------------------------------------------
  893. // plays the media
  894. //--------------------------------------------------------------------------
  895. STDMETHODIMP
  896. CMediaBarPlayer::Play()
  897. {
  898. if (!IsReady())
  899. return E_FAIL;
  900. return _spMediaElem->beginElement();
  901. }
  902. //+-------------------------------------------------------------------------
  903. // stops the media
  904. //--------------------------------------------------------------------------
  905. STDMETHODIMP
  906. CMediaBarPlayer::Stop()
  907. {
  908. if (!IsReady())
  909. return E_FAIL;
  910. return _spMediaElem->endElement();
  911. }
  912. //+-------------------------------------------------------------------------
  913. // pauses the media
  914. //--------------------------------------------------------------------------
  915. STDMETHODIMP
  916. CMediaBarPlayer::Pause()
  917. {
  918. if (!IsReady())
  919. return E_FAIL;
  920. return _spMediaElem->pauseElement();
  921. }
  922. //+-------------------------------------------------------------------------
  923. // resumes the media
  924. //--------------------------------------------------------------------------
  925. STDMETHODIMP
  926. CMediaBarPlayer::Resume()
  927. {
  928. if (!IsReady())
  929. return E_FAIL;
  930. return _spMediaElem->resumeElement();
  931. }
  932. //+-------------------------------------------------------------------------
  933. // seeks the media to the given progress
  934. //--------------------------------------------------------------------------
  935. STDMETHODIMP
  936. CMediaBarPlayer::Seek(double dblProgress)
  937. {
  938. HRESULT hr = E_FAIL;
  939. CComPtr<ITIMEState> spTimeState;
  940. double dblActiveDur = 0.0;
  941. double dblSeekTime = 0.0;
  942. VARIANT_BOOL vbActive = VARIANT_FALSE;
  943. if (!IsReady())
  944. {
  945. hr = E_FAIL;
  946. goto done;
  947. }
  948. if (!IsPlayList())
  949. {
  950. hr = _spMediaElem->get_currTimeState(&spTimeState);
  951. ERROREXIT(hr)
  952. hr = spTimeState->get_activeDur(&dblActiveDur);
  953. ERROREXIT(hr)
  954. hr = spTimeState->get_isActive(&vbActive);
  955. ERROREXIT(hr)
  956. // ISSUE: workaround for IE6 #20622
  957. // if the clip has ended, reactivate it in the paused state
  958. if (VARIANT_FALSE == vbActive)
  959. {
  960. _spMediaElem->beginElement();
  961. _spMediaElem->pauseElement();
  962. }
  963. if (TIME_INFINITE == dblActiveDur)
  964. {
  965. // we shouldn't be allowed to seek
  966. goto done;
  967. }
  968. else
  969. {
  970. Clamp(0.0, dblProgress, 1.0);
  971. dblSeekTime = dblActiveDur * dblProgress;
  972. }
  973. // seek the body
  974. hr = _spMediaElem->seekActiveTime(dblSeekTime);
  975. ERROREXIT(hr)
  976. hr = S_OK;
  977. }
  978. else
  979. {
  980. CComPtr<ITIMEPlayList> spPlayList;
  981. CComPtr<ITIMEPlayItem> spPlayItem;
  982. CComPtr<ITIMEMediaNative> spMediaNative;
  983. hr = _spMediaElem->get_playList(&spPlayList);
  984. if (SUCCEEDED(hr) && spPlayList)
  985. {
  986. hr = spPlayList->get_activeTrack(&spPlayItem);
  987. if (SUCCEEDED(hr) && spPlayItem)
  988. {
  989. spPlayItem->get_dur(&dblActiveDur);
  990. dblSeekTime = dblActiveDur * dblProgress;
  991. hr = _spMediaElem->QueryInterface(IID_TO_PPV(ITIMEMediaNative, &spMediaNative));
  992. if (SUCCEEDED(hr) && spMediaNative)
  993. {
  994. spMediaNative->seekActiveTrack(dblSeekTime);
  995. }
  996. }
  997. }
  998. }
  999. done:
  1000. return hr;
  1001. }
  1002. //+-------------------------------------------------------------------------
  1003. // Resize the video to fit in the given window size, preserving aspect ratio
  1004. //--------------------------------------------------------------------------
  1005. STDMETHODIMP
  1006. CMediaBarPlayer::Resize(LONG* plHeight, LONG* plWidth, BOOL fClampMaxSizeToNaturalSize)
  1007. {
  1008. HRESULT hr = E_FAIL;
  1009. long lMediaWidth = 0;
  1010. long lMediaHeight = 0;
  1011. long lResizeWidth = 0;
  1012. long lResizeHeight = 0;
  1013. float flWndAspect = 0.0f;
  1014. float flMediaAspect = 0.0f;
  1015. if (!IsReady() || !plHeight || !plWidth || (0 == (*plHeight)) || (0 == (*plWidth)))
  1016. {
  1017. goto done;
  1018. }
  1019. hr = _spMediaElem->get_mediaWidth(&lMediaWidth);
  1020. ERROREXIT(hr)
  1021. hr = _spMediaElem->get_mediaHeight(&lMediaHeight);
  1022. ERROREXIT(hr)
  1023. // do resize only if both dimensions are non-zero
  1024. if (0 != lMediaWidth && 0 != lMediaHeight)
  1025. {
  1026. // if natural media size <= window size and max size is clamped to natural media size
  1027. if ( fClampMaxSizeToNaturalSize
  1028. && lMediaWidth <= (*plWidth)
  1029. && lMediaHeight <= (*plHeight))
  1030. {
  1031. // set the media back to it's natural size
  1032. lResizeHeight = lMediaHeight;
  1033. lResizeWidth = lMediaWidth;
  1034. }
  1035. else
  1036. {
  1037. // resize the media to the window size
  1038. flWndAspect = (float) (*plHeight) / (float) (*plWidth);
  1039. flMediaAspect = (float) lMediaHeight / (float) lMediaWidth;
  1040. if (flMediaAspect <= flWndAspect)
  1041. {
  1042. // set width to window width and compute the height according to aspect ratio
  1043. lResizeWidth = (long)(*plWidth);
  1044. lResizeHeight = (long)(lResizeWidth * flMediaAspect);
  1045. }
  1046. else
  1047. {
  1048. // set height to window height and compute the width according to aspect ratio
  1049. lResizeHeight = (long)(*plHeight);
  1050. lResizeWidth = (long)(lResizeHeight / flMediaAspect);
  1051. }
  1052. }
  1053. // set the resized height and width on the HTML element
  1054. {
  1055. CComPtr<IHTMLStyle> spStyle;
  1056. CComPtr<IHTMLElement2> spHTMLElem;
  1057. hr = _spPlayerHTMLElem2->QueryInterface(IID_PPV_ARG(IHTMLElement2, &spHTMLElem));
  1058. ERROREXIT(hr)
  1059. // Using runtimeStyle instead of style.
  1060. // (Previously, we did the reverse as a work around for IE6 #20625. But now style is broken.)
  1061. hr = spHTMLElem->get_runtimeStyle(&spStyle);
  1062. ERROREXIT(hr)
  1063. hr = spStyle->put_pixelWidth(lResizeWidth);
  1064. ERROREXIT(hr)
  1065. hr = spStyle->put_pixelHeight(lResizeHeight);
  1066. ERROREXIT(hr)
  1067. }
  1068. }
  1069. *plWidth = lResizeWidth ;
  1070. *plHeight = lResizeHeight;
  1071. hr = S_OK;
  1072. done:
  1073. return hr;
  1074. }
  1075. ////////////////////////////////////////////////////////////////////////////
  1076. //
  1077. // IDispatch
  1078. //
  1079. ////////////////////////////////////////////////////////////////////////////
  1080. //+-------------------------------------------------------------------------
  1081. // Name: Invoke
  1082. //
  1083. // Abstract:
  1084. // This switches on the dispid looking for dispid's of events
  1085. // that it should handle. Note, this is called for all events
  1086. // fired from the window, only the selected events are handled.
  1087. //--------------------------------------------------------------------------
  1088. STDMETHODIMP CMediaBarPlayer::Invoke(
  1089. /* [in] */ DISPID dispIdMember,
  1090. /* [in] */ REFIID /*riid*/,
  1091. /* [in] */ LCID /*lcid*/,
  1092. /* [in] */ WORD /*wFlags*/,
  1093. /* [out][in] */ DISPPARAMS* pDispParams,
  1094. /* [out] */ VARIANT* pVarResult,
  1095. /* [out] */ EXCEPINFO* /*pExcepInfo*/,
  1096. /* [out] */ UINT* puArgErr)
  1097. {
  1098. HRESULT hr = E_FAIL;
  1099. switch (dispIdMember)
  1100. {
  1101. case 0: //this is the case for events that have been hooked using attachEvent
  1102. {
  1103. CComBSTR sbstrEvent;
  1104. CComPtr <IHTMLEventObj> pEventObj;
  1105. if ((NULL != pDispParams) && (NULL != pDispParams->rgvarg) &&
  1106. (V_VT(&(pDispParams->rgvarg[0])) == VT_DISPATCH))
  1107. {
  1108. hr = THR((pDispParams->rgvarg[0].pdispVal)->QueryInterface(IID_IHTMLEventObj, (void**)&pEventObj));
  1109. if (FAILED(hr))
  1110. {
  1111. goto done;
  1112. }
  1113. }
  1114. else
  1115. {
  1116. ASSERT(0 && "Unexpected dispparam values passed to CEventMgr::Invoke(dispid = 0)");
  1117. hr = E_UNEXPECTED;
  1118. goto done;
  1119. }
  1120. hr = THR(pEventObj->get_type(&sbstrEvent));
  1121. if (0 == StrCmpIW(WZ_TRACKCHANGE, sbstrEvent))
  1122. {
  1123. _OnTrackChange();
  1124. }
  1125. if (0 == StrCmpIW(WZ_MEDIACOMPLETE, sbstrEvent))
  1126. {
  1127. _OnMediaComplete();
  1128. }
  1129. else if (0 == StrCmpIW(WZ_MEDIAERROR, sbstrEvent))
  1130. {
  1131. int iErrCode = -1;
  1132. // Get the param if available
  1133. CComPtr<IHTMLEventObj2> spEventObj2;
  1134. CComVariant svarParam;
  1135. CComBSTR sbstrParam(WZ_PARAM);
  1136. hr = pEventObj->QueryInterface(IID_IHTMLEventObj2, (void**) &spEventObj2);
  1137. if (SUCCEEDED(hr) && sbstrParam.m_str)
  1138. {
  1139. // get the params
  1140. hr = spEventObj2->getAttribute(sbstrParam, 0, &svarParam);
  1141. if (SUCCEEDED(hr))
  1142. {
  1143. // change type to int
  1144. hr = svarParam.ChangeType(VT_I4);
  1145. if (SUCCEEDED(hr))
  1146. {
  1147. iErrCode = V_I4(&svarParam);
  1148. }
  1149. }
  1150. }
  1151. _OnMediaError(iErrCode);
  1152. }
  1153. else if (0 == StrCmpIW(WZ_END, sbstrEvent))
  1154. {
  1155. _OnEnd();
  1156. }
  1157. }
  1158. break;
  1159. case 259: // DISPID_DOCUMENTCOMPLETE
  1160. {
  1161. hr = _OnDocumentComplete();
  1162. ERROREXIT(hr)
  1163. }
  1164. break;
  1165. }
  1166. hr = S_OK;
  1167. done:
  1168. return S_OK;
  1169. }
  1170. ///////////////////////////////////////////////////////////////
  1171. // Name: _InitEventSink
  1172. //
  1173. // Abstract:
  1174. // Finds a connection point on the HTMLDocument interface
  1175. // and passes this as an event handler.
  1176. ///////////////////////////////////////////////////////////////
  1177. STDMETHODIMP
  1178. CMediaBarPlayer::_InitEventSink()
  1179. {
  1180. // Get a connection point to the container
  1181. CComPtr<IConnectionPointContainer> spDocCPC;
  1182. HRESULT hr = E_FAIL;
  1183. hr = _spBrowser->QueryInterface(IID_IConnectionPointContainer, (void**)&spDocCPC);
  1184. ERROREXIT(hr)
  1185. hr = THR(spDocCPC->FindConnectionPoint(DIID_DWebBrowserEvents2, &_spDocConPt ));
  1186. ERROREXIT(hr)
  1187. hr = THR(_spDocConPt->Advise(static_cast<IUnknown*>(static_cast<DWebBrowserEvents2*>(this)), &_dwDocumentEventConPtCookie));
  1188. ERROREXIT(hr)
  1189. hr = S_OK;
  1190. done:
  1191. if (FAILED(hr))
  1192. {
  1193. _DeInitEventSink();
  1194. }
  1195. return hr;
  1196. }
  1197. ///////////////////////////////////////////////////////////////
  1198. // Name: _DeInitEventSink
  1199. //
  1200. ///////////////////////////////////////////////////////////////
  1201. STDMETHODIMP
  1202. CMediaBarPlayer::_DeInitEventSink()
  1203. {
  1204. //release the document connection points
  1205. if (_spDocConPt)
  1206. {
  1207. if (_dwDocumentEventConPtCookie != 0)
  1208. {
  1209. IGNORE_HR(_spDocConPt->Unadvise(_dwDocumentEventConPtCookie));
  1210. }
  1211. _spDocConPt.Release();
  1212. }
  1213. _dwDocumentEventConPtCookie = 0;
  1214. return S_OK;
  1215. }
  1216. double
  1217. STDMETHODCALLTYPE
  1218. CMediaBarPlayer::GetTrackProgress()
  1219. {
  1220. if (IsReady())
  1221. {
  1222. if (!IsPlayList())
  1223. {
  1224. CComPtr<ITIMEState> spTimeState;
  1225. if (SUCCEEDED(_spMediaElem->get_currTimeState(&spTimeState)) && spTimeState)
  1226. {
  1227. double dblProgress = 0.0;
  1228. if (SUCCEEDED(spTimeState->get_progress(&dblProgress)))
  1229. {
  1230. return dblProgress;
  1231. }
  1232. }
  1233. }
  1234. else
  1235. {
  1236. CComPtr<ITIMEMediaNative> spMediaNative;
  1237. double dblProgress, dblActiveDur;
  1238. CComPtr<ITIMEPlayList> spPlayList;
  1239. CComPtr<ITIMEPlayItem> spPlayItem;
  1240. if (SUCCEEDED(_spMediaElem->get_playList(&spPlayList)) && spPlayList)
  1241. {
  1242. if (SUCCEEDED(spPlayList->get_activeTrack(&spPlayItem)) && spPlayItem)
  1243. {
  1244. spPlayItem->get_dur(&dblActiveDur);
  1245. if (SUCCEEDED(_spMediaElem->QueryInterface(IID_TO_PPV(ITIMEMediaNative, &spMediaNative))) && spMediaNative)
  1246. {
  1247. spMediaNative->get_activeTrackTime(&dblProgress);
  1248. return dblProgress / dblActiveDur;
  1249. }
  1250. }
  1251. }
  1252. }
  1253. }
  1254. return 0.0;
  1255. }
  1256. double
  1257. STDMETHODCALLTYPE
  1258. CMediaBarPlayer::GetTrackTime()
  1259. {
  1260. if (IsReady())
  1261. {
  1262. CComPtr<ITIMEState> spTimeState;
  1263. if (SUCCEEDED(_spMediaElem->get_currTimeState(&spTimeState)) && spTimeState)
  1264. {
  1265. double dblTime = 0.0;
  1266. if (SUCCEEDED(spTimeState->get_simpleTime(&dblTime)))
  1267. {
  1268. return dblTime;
  1269. }
  1270. }
  1271. }
  1272. return 0.0;
  1273. }
  1274. double
  1275. STDMETHODCALLTYPE
  1276. CMediaBarPlayer::GetTrackLength()
  1277. {
  1278. if (IsReady())
  1279. {
  1280. double dblDur = 0.0;
  1281. if (SUCCEEDED(_spMediaElem->get_mediaDur(&dblDur)))
  1282. return dblDur ;
  1283. }
  1284. return 0.0;
  1285. }
  1286. // Returns a progress between 0 and 100 and whether this is download or buffering progress
  1287. STDMETHODIMP
  1288. CMediaBarPlayer::GetBufProgress(double * pdblProg, ProgressType * ppt)
  1289. {
  1290. HRESULT hr = E_FAIL;
  1291. VARIANT_BOOL vb = VARIANT_FALSE;
  1292. if (!pdblProg || !ppt)
  1293. {
  1294. hr = E_INVALIDARG;
  1295. goto done;
  1296. }
  1297. if (!IsReady())
  1298. {
  1299. hr = E_FAIL;
  1300. goto done;
  1301. }
  1302. *pdblProg = 0.0;
  1303. *ppt = PT_None;
  1304. hr = _spMediaElem2->get_isStreamed(&vb);
  1305. if (FAILED(hr))
  1306. {
  1307. goto done;
  1308. }
  1309. if (VARIANT_TRUE == vb)
  1310. {
  1311. CComVariant svarBufProg;
  1312. hr = _spMediaElem2->get_bufferingProgress(&svarBufProg);
  1313. if (SUCCEEDED(hr))
  1314. {
  1315. *ppt = PT_Buffering;
  1316. if (SUCCEEDED(svarBufProg.ChangeType(VT_R8)))
  1317. {
  1318. *pdblProg = V_R8(&svarBufProg);
  1319. }
  1320. }
  1321. }
  1322. else
  1323. {
  1324. CComVariant svarDownloadProg;
  1325. hr = _spMediaElem2->get_downloadProgress(&svarDownloadProg);
  1326. if (SUCCEEDED(hr))
  1327. {
  1328. *ppt = PT_Download;
  1329. if (SUCCEEDED(svarDownloadProg.ChangeType(VT_R8)))
  1330. {
  1331. *pdblProg = V_R8(&svarDownloadProg);
  1332. }
  1333. }
  1334. }
  1335. done:
  1336. return hr;
  1337. }
  1338. VARIANT_BOOL STDMETHODCALLTYPE
  1339. CMediaBarPlayer::isMuted()
  1340. {
  1341. VARIANT_BOOL vbMuted = VARIANT_FALSE;
  1342. if (IsReady())
  1343. {
  1344. CComPtr<ITIMEState> spTimeState;
  1345. if (SUCCEEDED(_spMediaElem->get_currTimeState(&spTimeState)) && spTimeState)
  1346. {
  1347. spTimeState->get_isMuted(&vbMuted);
  1348. }
  1349. }
  1350. return vbMuted;
  1351. }
  1352. VARIANT_BOOL STDMETHODCALLTYPE
  1353. CMediaBarPlayer::isPaused()
  1354. {
  1355. VARIANT_BOOL vbPaused = VARIANT_FALSE;
  1356. if (IsReady())
  1357. {
  1358. CComPtr<ITIMEState> spTimeState;
  1359. if (SUCCEEDED(_spMediaElem->get_currTimeState(&spTimeState)) && spTimeState)
  1360. {
  1361. spTimeState->get_isPaused(&vbPaused);
  1362. }
  1363. }
  1364. return vbPaused;
  1365. }
  1366. VARIANT_BOOL STDMETHODCALLTYPE
  1367. CMediaBarPlayer::isStopped()
  1368. {
  1369. VARIANT_BOOL vbActive = VARIANT_FALSE;
  1370. if (IsReady())
  1371. {
  1372. CComPtr<ITIMEState> spTimeState;
  1373. if (SUCCEEDED(_spMediaElem->get_currTimeState(&spTimeState)) && spTimeState)
  1374. {
  1375. spTimeState->get_isActive(&vbActive);
  1376. }
  1377. }
  1378. return (vbActive ? VARIANT_FALSE : VARIANT_TRUE);
  1379. }
  1380. STDMETHODIMP
  1381. CMediaBarPlayer::Next()
  1382. {
  1383. return _SetTrack(TT_Next);;
  1384. }
  1385. STDMETHODIMP
  1386. CMediaBarPlayer::Prev()
  1387. {
  1388. return _SetTrack(TT_Prev);
  1389. }
  1390. STDMETHODIMP
  1391. CMediaBarPlayer::_SetTrack(TrackType tt)
  1392. {
  1393. HRESULT hr = E_FAIL;
  1394. CComPtr<ITIMEPlayList> spPlayList;
  1395. if (!IsReady())
  1396. {
  1397. goto done;
  1398. }
  1399. hr = _spMediaElem->get_playList(&spPlayList);
  1400. ERROREXIT(hr)
  1401. if (NULL != spPlayList.p)
  1402. {
  1403. if (TT_Next == tt)
  1404. {
  1405. hr = spPlayList->nextTrack();
  1406. ERROREXIT(hr)
  1407. }
  1408. else if (TT_Prev == tt)
  1409. {
  1410. hr = spPlayList->prevTrack();
  1411. ERROREXIT(hr)
  1412. }
  1413. }
  1414. hr = S_OK;
  1415. done:
  1416. return hr;
  1417. }
  1418. LONG_PTR
  1419. STDMETHODCALLTYPE
  1420. CMediaBarPlayer::GetPlayListItemIndex()
  1421. {
  1422. CComPtr<ITIMEPlayList> spPlayList;
  1423. long lIndex = -1;
  1424. if (IsReady())
  1425. {
  1426. if (SUCCEEDED(_spMediaElem->get_playList(&spPlayList)))
  1427. {
  1428. CComPtr<ITIMEPlayItem> spPlayItem;
  1429. if (spPlayList && SUCCEEDED(spPlayList->get_activeTrack(&spPlayItem)))
  1430. {
  1431. if (spPlayItem && SUCCEEDED(spPlayItem->get_index(&lIndex)))
  1432. return lIndex;
  1433. }
  1434. }
  1435. }
  1436. return (LONG_PTR)lIndex;
  1437. }
  1438. LONG_PTR
  1439. STDMETHODCALLTYPE
  1440. CMediaBarPlayer::GetPlayListItemCount()
  1441. {
  1442. CComPtr<ITIMEPlayList> spPlayList;
  1443. LONG lLength = 0;
  1444. if (IsReady())
  1445. {
  1446. if (SUCCEEDED(_spMediaElem->get_playList(&spPlayList)))
  1447. {
  1448. if (spPlayList && SUCCEEDED(spPlayList->get_length(&lLength)))
  1449. {
  1450. return lLength;
  1451. }
  1452. }
  1453. }
  1454. return lLength;
  1455. }
  1456. HRESULT
  1457. STDMETHODCALLTYPE
  1458. CMediaBarPlayer::SetActiveTrack( long lIndex)
  1459. {
  1460. CComPtr<ITIMEPlayList> spPlayList;
  1461. HRESULT hr = S_OK;
  1462. if (IsReady())
  1463. {
  1464. hr = _spMediaElem->get_playList(&spPlayList);
  1465. ERROREXIT(hr);
  1466. if (spPlayList)
  1467. {
  1468. VARIANT vIndex;
  1469. VariantInit(&vIndex);
  1470. vIndex.vt = VT_I4;
  1471. vIndex.lVal = lIndex;
  1472. hr = spPlayList->put_activeTrack(vIndex) ;
  1473. ERROREXIT(hr);
  1474. }
  1475. else
  1476. {
  1477. hr = S_FALSE;
  1478. }
  1479. }
  1480. done :
  1481. return hr ;
  1482. }
  1483. BOOL
  1484. STDMETHODCALLTYPE
  1485. CMediaBarPlayer::IsPausePossible()
  1486. {
  1487. if (IsReady())
  1488. {
  1489. VARIANT_BOOL vbIsPausePossible = VARIANT_FALSE;
  1490. if (SUCCEEDED(_spMediaElem->get_canPause(&vbIsPausePossible)))
  1491. {
  1492. return (vbIsPausePossible == VARIANT_TRUE) ? TRUE : FALSE;
  1493. }
  1494. }
  1495. return FALSE;
  1496. }
  1497. BOOL
  1498. STDMETHODCALLTYPE
  1499. CMediaBarPlayer::IsSeekPossible()
  1500. {
  1501. if (IsReady())
  1502. {
  1503. VARIANT_BOOL vbIsSeekPossible = VARIANT_FALSE;
  1504. if (SUCCEEDED(_spMediaElem->get_canSeek(&vbIsSeekPossible)))
  1505. {
  1506. return (vbIsSeekPossible == VARIANT_TRUE) ? TRUE : FALSE;
  1507. }
  1508. }
  1509. return FALSE;
  1510. }
  1511. BOOL
  1512. STDMETHODCALLTYPE
  1513. CMediaBarPlayer::IsStreaming()
  1514. {
  1515. if (IsReady())
  1516. {
  1517. VARIANT_BOOL vbIsStreaming = VARIANT_FALSE;
  1518. if (SUCCEEDED(_spMediaElem2->get_isStreamed(&vbIsStreaming)))
  1519. {
  1520. return (vbIsStreaming == VARIANT_TRUE) ? TRUE : FALSE;
  1521. }
  1522. }
  1523. return FALSE;
  1524. }
  1525. BOOL
  1526. STDMETHODCALLTYPE
  1527. CMediaBarPlayer::IsPlayList()
  1528. {
  1529. VARIANT_BOOL vbIsPlayList = VARIANT_FALSE;
  1530. if (IsReady())
  1531. {
  1532. if (SUCCEEDED(_spMediaElem->get_hasPlayList(&vbIsPlayList)))
  1533. {
  1534. return (vbIsPlayList == VARIANT_TRUE) ? TRUE : FALSE;
  1535. }
  1536. }
  1537. return FALSE;
  1538. }
  1539. BOOL
  1540. STDMETHODCALLTYPE
  1541. CMediaBarPlayer::IsSkippable()
  1542. {
  1543. BOOL fRet = TRUE;
  1544. // We need to check if the client has specified CLIENTSKIP="no" and respect that. This is to prevent
  1545. // the media bar from allowing the user to skip server-side stuff, which is a no-no. There are legal restrictions
  1546. // related to this.
  1547. CComDispatchDriverEx spWMP;
  1548. if (_spMediaElem && SUCCEEDED(_spMediaElem->get_playerObject(&spWMP)) && spWMP)
  1549. {
  1550. CComVariant vtControls;
  1551. HRESULT hr = spWMP.GetPropertyByName(L"controls", &vtControls);
  1552. if (SUCCEEDED(hr))
  1553. {
  1554. CComDispatchDriverEx pwmpControls;
  1555. pwmpControls = vtControls;
  1556. // We're only checking for next (but not back), and assuming that NOSKIP will affect only "next".
  1557. CComVariant vtNext = "Next";
  1558. CComVariant vtEnabled;
  1559. hr = pwmpControls.GetPropertyByName1(L"isAvailable", &vtNext, &vtEnabled);
  1560. if (SUCCEEDED(hr) && (V_VT(&vtEnabled) == VT_BOOL))
  1561. {
  1562. fRet = (V_BOOL(&vtEnabled) == VARIANT_TRUE);
  1563. }
  1564. }
  1565. }
  1566. return fRet;
  1567. }
  1568. #ifdef SINKWMP
  1569. HRESULT CMediaBarPlayer::InitWMPSink()
  1570. {
  1571. if (!_spWMP)
  1572. {
  1573. if (SUCCEEDED(_spMediaElem->get_playerObject(&_spWMP)))
  1574. {
  1575. CComPtr<IConnectionPointContainer> pcpc;
  1576. HRESULT hr = _spWmp->QueryInterface(IID_TO_PPV(IConnectionPointContainer, &pcpc));
  1577. if (SUCCEEDED(hr))
  1578. {
  1579. hr = pcpc->FindConnectionPoint(DIID__WMPOCXEvents, &_spWMPCP);
  1580. }
  1581. if (SUCCEEDED(hr))
  1582. {
  1583. hr = _spWMPCP->Advise(GetUnknown(), &_dwWMPCookie);
  1584. if (FAILED(hr))
  1585. {
  1586. m_pcpMediaEvents.Release();
  1587. m_dwMediaEventsCookie = 0;
  1588. }
  1589. }
  1590. }
  1591. }
  1592. return S_OK;
  1593. }
  1594. #endif
  1595. HRESULT CMediaBarPlayer::GetProp(IDispatch* pDispatch, OLECHAR* pwzProp, VARIANT* pvarResult, DISPPARAMS* pParams)
  1596. {
  1597. DISPID dispid = NULL;
  1598. HRESULT hr = S_OK;
  1599. DISPPARAMS params = {NULL, NULL, 0, 0};
  1600. if (!pParams)
  1601. {
  1602. pParams = &params;
  1603. }
  1604. if (!pDispatch)
  1605. {
  1606. hr = E_POINTER;
  1607. goto done;
  1608. }
  1609. hr = pDispatch->GetIDsOfNames(IID_NULL, &pwzProp, 1, LOCALE_SYSTEM_DEFAULT, &dispid);
  1610. if (FAILED(hr))
  1611. {
  1612. goto done;
  1613. }
  1614. hr = pDispatch->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET,
  1615. pParams, pvarResult, NULL, NULL);
  1616. if (FAILED(hr))
  1617. {
  1618. goto done;
  1619. }
  1620. done:
  1621. return hr;
  1622. }
  1623. HRESULT CMediaBarPlayer::CallMethod(IDispatch* pDispatch, OLECHAR* pwzMethod, VARIANT* pvarResult, VARIANT* pvarArgument1)
  1624. {
  1625. DISPID dispid = NULL;
  1626. HRESULT hr = S_OK;
  1627. DISPPARAMS params = {pvarArgument1, NULL, 0, 0};
  1628. if (NULL != pvarArgument1)
  1629. {
  1630. params.cArgs = 1;
  1631. }
  1632. if (!pDispatch)
  1633. {
  1634. hr = E_POINTER;
  1635. goto done;
  1636. }
  1637. hr = pDispatch->GetIDsOfNames(IID_NULL, &pwzMethod, 1, LOCALE_SYSTEM_DEFAULT, &dispid);
  1638. if (FAILED(hr))
  1639. {
  1640. goto done;
  1641. }
  1642. hr = pDispatch->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD,
  1643. &params, pvarResult, NULL, NULL);
  1644. if (FAILED(hr))
  1645. {
  1646. goto done;
  1647. }
  1648. done:
  1649. return hr;
  1650. }