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.

1097 lines
30 KiB

  1. //------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 2001
  5. //
  6. // File: mbBehave.cpp
  7. //
  8. // Contents: mediaBar player behavior
  9. //
  10. // Classes: CMediaBehavior
  11. //
  12. //------------------------------------------------------------------------
  13. #include "priv.h"
  14. #define INITGUID // pull in additional declaration for private mediabar IIDs
  15. #include "initguid.h"
  16. #include "mbBehave.h"
  17. #undef INITGUID
  18. #include "mediaBand.h"
  19. #include "mediautil.h"
  20. #include "varutil.h"
  21. #include <mluisupp.h>
  22. #include "resource.h"
  23. //================================================================================================
  24. // CMediaBehavior
  25. //================================================================================================
  26. #define NO_COOKIE -1
  27. // event names fired from this behavior:
  28. // NOTE: need to match the enums in the mbBehave.h with this array!!!
  29. struct _eventInfo {
  30. LONG levtCookie;
  31. LPWSTR pwszName;
  32. } s_behaviorEvents[] =
  33. {
  34. NO_COOKIE, L"OnOpenStateChange",
  35. NO_COOKIE, L"OnPlayStateChange",
  36. NO_COOKIE, L"OnShow",
  37. NO_COOKIE, L"OnHide",
  38. };
  39. #ifndef WMPCOREEVENT_BASE
  40. // ISSUE/010430/davidjen should be pulled in from wmp.idl, but this file is not part of source tree
  41. #define INITGUID // define GUID, not only declare it
  42. #include "initguid.h"
  43. DEFINE_GUID(DIID__WMPOCXEvents,0x6BF52A51,0x394A,0x11d3,0xB1,0x53,0x00,0xC0,0x4F,0x79,0xFA,0xA6);
  44. #define WMPCOREEVENT_BASE 5000
  45. #define DISPID_WMPCOREEVENT_OPENSTATECHANGE (WMPCOREEVENT_BASE + 1)
  46. #define WMPCOREEVENT_CONTROL_BASE 5100
  47. #define DISPID_WMPCOREEVENT_PLAYSTATECHANGE (WMPCOREEVENT_CONTROL_BASE + 1)
  48. #undef INITGUID
  49. #endif
  50. // class factories
  51. //------------------------------------------------------------------------
  52. CMediaBehavior *
  53. CMediaBehavior_CreateInstance(CMediaBand* pHost)
  54. {
  55. return new CMediaBehavior(pHost);
  56. }
  57. //------------------------------------------------------------------------
  58. CMediaItem *
  59. CMediaItem_CreateInstance(CMediaBehavior* pHost)
  60. {
  61. return new CMediaItem(pHost);
  62. }
  63. //------------------------------------------------------------------------
  64. CMediaItemNext *
  65. CMediaItemNext_CreateInstance(CMediaBehavior* pHost)
  66. {
  67. return new CMediaItemNext(pHost);
  68. }
  69. //------------------------------------------------------------------------
  70. CPlaylistInfo *
  71. CPlaylistInfo_CreateInstance(CMediaBehavior* pHost)
  72. {
  73. return new CPlaylistInfo(pHost);
  74. }
  75. ///////////////////////////////////////////////////////////////////////////////
  76. ///////////////////////////////////////////////////////////////////////////////
  77. //
  78. // class CMediaBehavior
  79. //
  80. ///////////////////////////////////////////////////////////////////////////////
  81. ///////////////////////////////////////////////////////////////////////////////
  82. //------------------------------------------------------------------------
  83. CMediaBehavior::CMediaBehavior(CMediaBand* pHost)
  84. : CImpIDispatch(LIBID_BrowseUI, 1, 0, IID_IMediaBehavior),
  85. _cRef(0),
  86. _dwcpCookie(0),
  87. _fDisabledUI(FALSE),
  88. _fPlaying(FALSE)
  89. {
  90. ASSERT(pHost);
  91. _pHost = pHost;
  92. if (_pHost)
  93. {
  94. _pHost->AddRef();
  95. HRESULT hr = _pHost->addProxy((IContentProxy*)this);
  96. ASSERT(SUCCEEDED(hr));
  97. }
  98. }
  99. //------------------------------------------------------------------------
  100. CMediaBehavior::~CMediaBehavior()
  101. {
  102. Detach(); // to be sure...
  103. if (_pHost)
  104. _pHost->Release();
  105. }
  106. //------------------------------------------------------------------------
  107. STDMETHODIMP CMediaBehavior::QueryInterface(REFIID riid, void **ppv)
  108. {
  109. static const QITAB qit[] =
  110. {
  111. QITABENT(CMediaBehavior, IElementBehavior),
  112. QITABENT(CMediaBehavior, IMediaBehavior),
  113. QITABENT(CMediaBehavior, IDispatch),
  114. QITABENTMULTI2(CMediaBehavior, DIID__WMPOCXEvents, IDispatch),
  115. QITABENT(CMediaBehavior, IContentProxy),
  116. QITABENT(CMediaBehavior, IMediaBehaviorContentProxy),
  117. { 0 },
  118. };
  119. return QISearch(this, qit, riid, ppv);
  120. }
  121. //------------------------------------------------------------------------
  122. STDMETHODIMP CMediaBehavior::Detach(void)
  123. {
  124. _ConnectToWmpEvents(FALSE);
  125. // detach from behavior site
  126. if (_pHost)
  127. {
  128. _pHost->removeProxy(SAFECAST(this, IContentProxy*)); // optimize: _pHost saves ptr as IContentProxy, this saves a QI
  129. _pHost->Release();
  130. _pHost = NULL;
  131. }
  132. _fPlaying = FALSE;
  133. if (_apMediaItems != NULL)
  134. {
  135. int cnt = _apMediaItems.GetPtrCount();
  136. for (int i = 0; i < cnt; i++)
  137. {
  138. CMediaItem* pItem = _apMediaItems.GetPtr(i);
  139. if (pItem)
  140. pItem->Release();
  141. }
  142. _apMediaItems.Destroy();
  143. }
  144. _pBehaviorSite.Release();
  145. _pBehaviorSiteOM.Release();
  146. for (int i = 0; i < ARRAYSIZE(s_behaviorEvents); i++)
  147. {
  148. s_behaviorEvents[i].levtCookie = NO_COOKIE;
  149. }
  150. return S_OK;
  151. }
  152. //------------------------------------------------------------------------
  153. STDMETHODIMP CMediaBehavior::Init(IElementBehaviorSite* pBehaviorSite)
  154. {
  155. ASSERT(pBehaviorSite);
  156. if (pBehaviorSite == NULL) return E_POINTER;
  157. _pBehaviorSite = pBehaviorSite;
  158. pBehaviorSite->QueryInterface(IID_PPV_ARG(IElementBehaviorSiteOM, &_pBehaviorSiteOM));
  159. ASSERT(_pBehaviorSiteOM != NULL);
  160. return S_OK;
  161. }
  162. //------------------------------------------------------------------------
  163. STDMETHODIMP CMediaBehavior::Notify(LONG lEvent, VARIANT* pVar)
  164. {
  165. // ISSUE/000923/davidjen
  166. // these enums require behavior.idl; this idl is only available in inetcore,
  167. // might have to be moved to shell/published or mergedcomponents
  168. /*
  169. switch (lEvent) {
  170. case BEHAVIOREVENT_CONTENTCHANGE:
  171. break;
  172. case BEHAVIOREVENT_DOCUMENTREADY:
  173. break;
  174. }
  175. */
  176. return S_OK;
  177. }
  178. // *** IDispatch ***
  179. //------------------------------------------------------------------------
  180. STDMETHODIMP CMediaBehavior::Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo, UINT * puArgErr)
  181. {
  182. if (!_ProcessEvent(dispidMember, pdispparams->cArgs, pdispparams->rgvarg))
  183. {
  184. return CImpIDispatch::Invoke(dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);
  185. }
  186. return S_OK;
  187. }
  188. //------------------------------------------------------------------------
  189. BOOL CMediaBehavior::_ProcessEvent(DISPID dispid, long lCount, VARIANT varParams[])
  190. {
  191. BOOL fHandled = FALSE;
  192. switch (dispid)
  193. {
  194. case DISPID_WMPCOREEVENT_PLAYSTATECHANGE:
  195. ASSERT(lCount == 1);
  196. ASSERT(V_VT(&varParams[0]) == VT_I4);
  197. fireEvent(OnPlayStateChange);
  198. fHandled = TRUE;
  199. break;
  200. case DISPID_WMPCOREEVENT_OPENSTATECHANGE:
  201. ASSERT(lCount == 1);
  202. ASSERT(V_VT(&varParams[0]) == VT_I4);
  203. fireEvent(OnOpenStateChange);
  204. fHandled = TRUE;
  205. break;
  206. default:
  207. fHandled = FALSE;
  208. break;
  209. }
  210. return fHandled;
  211. }
  212. // *** IMediaBehavior ***
  213. //------------------------------------------------------------------------
  214. STDMETHODIMP CMediaBehavior::playURL(BSTR bstrURL, BSTR bstrMIME)
  215. {
  216. if (!_pHost)
  217. {
  218. return E_UNEXPECTED;
  219. }
  220. _fPlaying = TRUE;
  221. _pHost->playURL(bstrURL, bstrMIME);
  222. return S_OK;
  223. }
  224. //------------------------------------------------------------------------
  225. STDMETHODIMP CMediaBehavior::stop()
  226. {
  227. if (!_pHost)
  228. {
  229. return E_UNEXPECTED;
  230. }
  231. return IUnknown_Exec(SAFECAST(_pHost, IMediaBar*), &CLSID_MediaBand, FCIDM_MEDIABAND_STOP, 0, NULL, NULL);
  232. }
  233. //------------------------------------------------------------------------
  234. STDMETHODIMP CMediaBehavior::playNext()
  235. {
  236. if (!_pHost)
  237. {
  238. return E_UNEXPECTED;
  239. }
  240. return IUnknown_Exec(SAFECAST(_pHost, IMediaBar*), &CLSID_MediaBand, FCIDM_MEDIABAND_NEXT, 0, NULL, NULL);
  241. }
  242. //------------------------------------------------------------------------
  243. STDMETHODIMP CMediaBehavior::get_currentItem(IMediaItem **ppMediaItem)
  244. {
  245. if (ppMediaItem == NULL)
  246. return E_POINTER;
  247. *ppMediaItem = NULL;
  248. HRESULT hr = S_OK;
  249. if (_apMediaItems == NULL) {
  250. _apMediaItems.Create(2);
  251. }
  252. if (_apMediaItems == NULL)
  253. return E_OUTOFMEMORY;
  254. CMediaItem *pItem = CMediaItem_CreateInstance(this);
  255. if (pItem)
  256. {
  257. pItem->AddRef(); // keep object alive with ref count >= 1
  258. hr = pItem->AttachToWMP();
  259. if (SUCCEEDED(hr))
  260. {
  261. hr = pItem->QueryInterface(IID_PPV_ARG(IMediaItem, ppMediaItem));
  262. // pItem->AddRef();
  263. // _apMediaItems.AppendPtr(pItem); // keep a ref for us
  264. }
  265. pItem->Release();
  266. }
  267. else
  268. {
  269. hr = E_OUTOFMEMORY;
  270. }
  271. return hr;
  272. }
  273. //------------------------------------------------------------------------
  274. STDMETHODIMP CMediaBehavior::get_nextItem(IMediaItem **ppMediaItem)
  275. {
  276. if (ppMediaItem == NULL)
  277. return E_POINTER;
  278. *ppMediaItem = NULL;
  279. HRESULT hr = S_OK;
  280. if (_apMediaItems == NULL) {
  281. _apMediaItems.Create(2);
  282. }
  283. if (_apMediaItems == NULL)
  284. return E_OUTOFMEMORY;
  285. CMediaItemNext *pItem = CMediaItemNext_CreateInstance(this);
  286. if (pItem)
  287. {
  288. pItem->AddRef(); // keep object alive with ref count >= 1
  289. hr = pItem->AttachToWMP();
  290. if (SUCCEEDED(hr))
  291. {
  292. hr = pItem->QueryInterface(IID_PPV_ARG(IMediaItem, ppMediaItem));
  293. // pItem->AddRef();
  294. // _apMediaItems.AppendPtr(pItem); // keep a ref for us
  295. }
  296. pItem->Release();
  297. }
  298. else
  299. {
  300. hr = E_OUTOFMEMORY;
  301. }
  302. return hr;
  303. }
  304. //------------------------------------------------------------------------
  305. STDMETHODIMP CMediaBehavior::get_playlistInfo(IPlaylistInfo **ppPlaylistInfo)
  306. {
  307. if (ppPlaylistInfo == NULL)
  308. return E_POINTER;
  309. *ppPlaylistInfo = NULL;
  310. HRESULT hr = S_OK;
  311. if (_apMediaItems == NULL) {
  312. _apMediaItems.Create(2);
  313. }
  314. if (_apMediaItems == NULL)
  315. return E_OUTOFMEMORY;
  316. CPlaylistInfo *pInfo = CPlaylistInfo_CreateInstance(this);
  317. if (pInfo)
  318. {
  319. pInfo->AddRef(); // keep object alive with ref count >= 1
  320. hr = pInfo->AttachToWMP();
  321. if (SUCCEEDED(hr))
  322. {
  323. hr = pInfo->QueryInterface(IID_PPV_ARG(IPlaylistInfo, ppPlaylistInfo));
  324. // pItem->AddRef();
  325. // _apMediaItems.AppendPtr(pInfo); // keep a ref for us
  326. }
  327. pInfo->Release();
  328. }
  329. else
  330. {
  331. hr = E_OUTOFMEMORY;
  332. }
  333. return hr;
  334. }
  335. //------------------------------------------------------------------------
  336. STDMETHODIMP CMediaBehavior::get_hasNextItem(VARIANT_BOOL *pfhasNext)
  337. {
  338. if (pfhasNext == NULL)
  339. {
  340. return E_POINTER;
  341. }
  342. *pfhasNext = VARIANT_FALSE;
  343. if (!_pHost)
  344. {
  345. return E_UNEXPECTED;
  346. }
  347. LONG currTrack = 0;
  348. LONG cntTracks = 0;
  349. HRESULT hr = getPlayListIndex(&currTrack, &cntTracks);
  350. if (SUCCEEDED(hr))
  351. {
  352. *pfhasNext = ((currTrack >= 0) && (currTrack < cntTracks - 1)) ? VARIANT_TRUE : VARIANT_FALSE;
  353. }
  354. return S_OK;
  355. }
  356. //------------------------------------------------------------------------
  357. STDMETHODIMP CMediaBehavior::get_playState(mbPlayState *pps)
  358. {
  359. if (pps == NULL)
  360. return E_POINTER;
  361. *pps = mbpsUndefined;
  362. CComDispatchDriver pwmpPlayer;
  363. HRESULT hr = getWMP(&pwmpPlayer);
  364. if (FAILED(hr) || !pwmpPlayer)
  365. {
  366. // player not created yet, state undefined
  367. *pps = mbpsUndefined;
  368. return S_OK;
  369. }
  370. CComVariant vtPlayState;
  371. hr = pwmpPlayer.GetPropertyByName(L"playState", &vtPlayState);
  372. if (SUCCEEDED(hr) && (V_VT(&vtPlayState) == VT_I4))
  373. {
  374. *pps = (mbPlayState) V_I4(&vtPlayState);
  375. }
  376. return hr;
  377. }
  378. //------------------------------------------------------------------------
  379. STDMETHODIMP CMediaBehavior::get_openState(mbOpenState *pos)
  380. {
  381. if (pos == NULL)
  382. return E_POINTER;
  383. *pos = mbosUndefined;
  384. CComDispatchDriver pwmpPlayer;
  385. HRESULT hr = getWMP(&pwmpPlayer);
  386. if (FAILED(hr) || !pwmpPlayer)
  387. {
  388. // player not created yet, state undefined
  389. *pos = mbosUndefined;
  390. return S_OK;
  391. }
  392. CComVariant vtOpenState;
  393. hr = pwmpPlayer.GetPropertyByName(L"openState", &vtOpenState);
  394. if (SUCCEEDED(hr) && (V_VT(&vtOpenState) == VT_I4))
  395. {
  396. *pos = (mbOpenState) V_I4(&vtOpenState);
  397. }
  398. return hr;
  399. }
  400. //------------------------------------------------------------------------
  401. STDMETHODIMP CMediaBehavior::get_enabled(VARIANT_BOOL *pbEnabled)
  402. {
  403. if (pbEnabled == NULL)
  404. return E_POINTER;
  405. *pbEnabled = VARIANT_FALSE;
  406. CComDispatchDriver pwmpPlayer;
  407. HRESULT hr = getWMP(&pwmpPlayer);
  408. if (FAILED(hr) || !pwmpPlayer)
  409. {
  410. // player not created yet, state undefined
  411. *pbEnabled = VARIANT_FALSE;
  412. return S_FALSE;
  413. }
  414. CComVariant vtEnabled;
  415. hr = pwmpPlayer.GetPropertyByName(L"enabled", &vtEnabled);
  416. if (SUCCEEDED(hr) && (V_VT(&vtEnabled) == VT_BOOL))
  417. {
  418. *pbEnabled = V_BOOL(&vtEnabled);
  419. }
  420. return hr;
  421. }
  422. //------------------------------------------------------------------------
  423. STDMETHODIMP CMediaBehavior::put_enabled(VARIANT_BOOL bEnabled)
  424. {
  425. CComDispatchDriver pwmpPlayer;
  426. HRESULT hr = getWMP(&pwmpPlayer);
  427. if (FAILED(hr) || !pwmpPlayer)
  428. {
  429. // player not created yet, fire exception to let scrip know it has no control
  430. return E_UNEXPECTED;
  431. }
  432. CComVariant vtEnabled = bEnabled;
  433. return pwmpPlayer.PutPropertyByName(L"enabled", &vtEnabled);
  434. }
  435. //------------------------------------------------------------------------
  436. STDMETHODIMP CMediaBehavior::get_disabledUI(VARIANT_BOOL *pbDisabled)
  437. {
  438. if (pbDisabled == NULL)
  439. return E_POINTER;
  440. *pbDisabled = _fDisabledUI ? VARIANT_TRUE : VARIANT_FALSE;
  441. return S_OK;
  442. }
  443. //------------------------------------------------------------------------
  444. STDMETHODIMP CMediaBehavior::put_disabledUI(VARIANT_BOOL bDisable)
  445. {
  446. _fDisabledUI = bDisable;
  447. // tell mediaband
  448. if (_pHost)
  449. {
  450. _pHost->OnDisableUIChanged(_fDisabledUI);
  451. }
  452. return S_OK;
  453. }
  454. //
  455. // *** IMediaBehaviorContentProxy ***
  456. //------------------------------------------------------------------------
  457. STDMETHODIMP CMediaBehavior::OnCreatedPlayer(void)
  458. {
  459. return _ConnectToWmpEvents(TRUE);
  460. }
  461. //------------------------------------------------------------------------
  462. STDMETHODIMP CMediaBehavior::fireEvent(enum contentProxyEvent event)
  463. {
  464. ASSERT(_pBehaviorSiteOM != NULL); // called too early, must have received Init() call from Trident first!
  465. if (!_pBehaviorSiteOM)
  466. return E_UNEXPECTED;
  467. if ((event < 0) || (event >= ARRAYSIZE(s_behaviorEvents)))
  468. return E_INVALIDARG;
  469. struct _eventInfo *pEvtInfo = &s_behaviorEvents[event];
  470. HRESULT hr = S_OK;
  471. // don't have cookie yet, need to register event first!
  472. if (pEvtInfo->levtCookie == NO_COOKIE)
  473. {
  474. // register event with behavior site
  475. hr = _pBehaviorSiteOM->RegisterEvent(pEvtInfo->pwszName, 0, &pEvtInfo->levtCookie);
  476. ASSERT(SUCCEEDED(hr));
  477. if (FAILED(hr))
  478. return hr;
  479. }
  480. if (pEvtInfo->levtCookie == NO_COOKIE)
  481. return E_UNEXPECTED;
  482. CComPtr<IHTMLEventObj> pEvt;
  483. hr = _pBehaviorSiteOM->CreateEventObject(&pEvt);
  484. if (FAILED(hr))
  485. return hr;
  486. // fire into script:
  487. return _pBehaviorSiteOM->FireEvent(pEvtInfo->levtCookie, pEvt);
  488. }
  489. //------------------------------------------------------------------------
  490. STDMETHODIMP CMediaBehavior::detachPlayer(void)
  491. {
  492. return _ConnectToWmpEvents(FALSE);
  493. }
  494. // *** IMediaBehaviorContentProxy ***
  495. //------------------------------------------------------------------------
  496. STDMETHODIMP CMediaBehavior::OnUserOverrideDisableUI()
  497. {
  498. return put_disabledUI(VARIANT_FALSE);
  499. }
  500. //------------------------------------------------------------------------
  501. STDMETHODIMP CMediaBehavior::IsDisableUIRequested(BOOL *pfRequested)
  502. {
  503. if (!pfRequested)
  504. {
  505. return E_POINTER;
  506. }
  507. *pfRequested = _fDisabledUI;
  508. return S_OK;
  509. }
  510. //------------------------------------------------------------------------
  511. STDMETHODIMP CMediaBehavior::IsNextEnabled(BOOL *pfEnabled)
  512. {
  513. if (!pfEnabled)
  514. {
  515. return E_POINTER;
  516. }
  517. *pfEnabled = FALSE;
  518. CComDispatchDriverEx pwmpPlayer;
  519. HRESULT hr = getWMP(&pwmpPlayer);
  520. if (SUCCEEDED(hr) && pwmpPlayer)
  521. {
  522. CComVariant vtControls;
  523. hr = pwmpPlayer.GetPropertyByName(L"controls", &vtControls);
  524. if (SUCCEEDED(hr))
  525. {
  526. CComDispatchDriverEx pwmpControls;
  527. pwmpControls = vtControls;
  528. CComVariant vtNext = "Next";
  529. CComVariant vtEnabled;
  530. hr = pwmpControls.GetPropertyByName1(L"isAvailable", &vtNext, &vtEnabled);
  531. if (SUCCEEDED(hr) && (V_VT(&vtEnabled) == VT_BOOL))
  532. {
  533. *pfEnabled = (V_BOOL(&vtEnabled) == VARIANT_TRUE);
  534. }
  535. }
  536. }
  537. return S_OK;
  538. }
  539. //------------------------------------------------------------------------
  540. HRESULT CMediaBehavior::getWMP(IDispatch **ppPlayer)
  541. {
  542. if (ppPlayer == NULL)
  543. return E_POINTER;
  544. *ppPlayer = NULL;
  545. if (!CMediaBarUtil::IsWMP7OrGreaterCapable() || !_pHost)
  546. {
  547. return E_UNEXPECTED;
  548. }
  549. if (!_fPlaying)
  550. {
  551. return E_ACCESSDENIED;
  552. }
  553. HRESULT hr = E_UNEXPECTED;
  554. CComPtr<IUnknown> pMediaPlayer;
  555. hr = _pHost->getMediaPlayer(&pMediaPlayer);
  556. // getMediaPlayer can return NULL and S_FALSE if player isn't loaded yet!
  557. if (SUCCEEDED(hr) && pMediaPlayer)
  558. {
  559. CComQIPtr<ITIMEMediaElement, &IID_ITIMEMediaElement> pMediaElem = pMediaPlayer;
  560. if (pMediaElem)
  561. {
  562. return pMediaElem->get_playerObject(ppPlayer);
  563. }
  564. else
  565. {
  566. hr = E_NOINTERFACE;
  567. }
  568. }
  569. return hr;
  570. }
  571. //------------------------------------------------------------------------
  572. HRESULT CMediaBehavior::getPlayListIndex(LONG *plIndex, LONG *plCount)
  573. {
  574. if (!_pHost)
  575. {
  576. return E_UNEXPECTED;
  577. }
  578. CComPtr<IUnknown> pMediaPlayer;
  579. HRESULT hr = _pHost->getMediaPlayer(&pMediaPlayer);
  580. // getMediaPlayer can return NULL and S_FALSE if player isn't loaded yet!
  581. if (SUCCEEDED(hr) && pMediaPlayer)
  582. {
  583. CComQIPtr<ITIMEMediaElement, &IID_ITIMEMediaElement> pMediaElem = pMediaPlayer;
  584. if (pMediaElem)
  585. {
  586. CComPtr<ITIMEPlayList> pPlayList;
  587. if (SUCCEEDED(pMediaElem->get_playList(&pPlayList)) && pPlayList)
  588. {
  589. // current track index
  590. if (plIndex)
  591. {
  592. CComPtr<ITIMEPlayItem> pPlayItem;
  593. if (SUCCEEDED(pPlayList->get_activeTrack(&pPlayItem)) && pPlayItem)
  594. {
  595. hr = pPlayItem->get_index(plIndex);
  596. }
  597. }
  598. // number of tracks in playlist
  599. if (plCount)
  600. {
  601. hr = pPlayList->get_length(plCount);
  602. }
  603. }
  604. }
  605. }
  606. return hr;
  607. }
  608. //------------------------------------------------------------------------
  609. HRESULT CMediaBehavior::_ConnectToWmpEvents(BOOL fConnect)
  610. {
  611. if ( (fConnect && (_dwcpCookie != 0))
  612. || (!fConnect && (_dwcpCookie == 0))
  613. || !_pHost)
  614. {
  615. return S_FALSE; // no change in connection or no host
  616. }
  617. CComPtr<IDispatch> pwmpPlayer;
  618. HRESULT hr = getWMP(&pwmpPlayer);
  619. if (SUCCEEDED(hr) && pwmpPlayer)
  620. {
  621. return ConnectToConnectionPoint(SAFECAST(this, IDispatch*),
  622. DIID__WMPOCXEvents, fConnect, pwmpPlayer, &_dwcpCookie, NULL);
  623. }
  624. return hr;
  625. }
  626. ///////////////////////////////////////////////////////////////////////////////
  627. ///////////////////////////////////////////////////////////////////////////////
  628. //
  629. // class CWMPWrapper
  630. //
  631. ///////////////////////////////////////////////////////////////////////////////
  632. ///////////////////////////////////////////////////////////////////////////////
  633. //------------------------------------------------------------------------
  634. CWMPWrapper::CWMPWrapper(CMediaBehavior* pHost)
  635. : _cRef(0),
  636. _fStale(FALSE)
  637. {
  638. ASSERT(pHost);
  639. _pHost = pHost;
  640. if (_pHost)
  641. _pHost->AddRef();
  642. }
  643. //------------------------------------------------------------------------
  644. CWMPWrapper::~CWMPWrapper()
  645. {
  646. if (_pHost)
  647. _pHost->Release();
  648. }
  649. //------------------------------------------------------------------------
  650. HRESULT CWMPWrapper::_getVariantProp(LPCOLESTR pwszPropName, VARIANT *pvtParam, VARIANT *pvtValue, BOOL fCallMethod)
  651. {
  652. if (pvtValue == NULL)
  653. return E_POINTER;
  654. HRESULT hr = S_FALSE;
  655. VariantInit(pvtValue);
  656. if (!_fStale && _pwmpWrapper)
  657. {
  658. if (fCallMethod)
  659. {
  660. if (pvtParam != NULL)
  661. {
  662. hr = _pwmpWrapper.Invoke1(pwszPropName, pvtParam, pvtValue);
  663. }
  664. else
  665. {
  666. hr = _pwmpWrapper.Invoke0(pwszPropName, pvtValue);
  667. }
  668. }
  669. else
  670. {
  671. if (pvtParam != NULL)
  672. {
  673. hr = _pwmpWrapper.GetPropertyByName1(pwszPropName, pvtParam, pvtValue);
  674. }
  675. else
  676. {
  677. hr = _pwmpWrapper.GetPropertyByName(pwszPropName, pvtValue);
  678. }
  679. }
  680. }
  681. return hr;
  682. }
  683. //------------------------------------------------------------------------
  684. HRESULT CWMPWrapper::_getStringProp(LPCOLESTR pwszPropName, VARIANT *pvtParam, OUT BSTR *pbstrValue, BOOL fCallMethod)
  685. {
  686. if (pbstrValue == NULL)
  687. return E_POINTER;
  688. *pbstrValue = NULL;
  689. CComVariant vtValue;
  690. HRESULT hr = _getVariantProp(pwszPropName, pvtParam, &vtValue, fCallMethod);
  691. if (SUCCEEDED(hr) && (V_VT(&vtValue) == VT_BSTR))
  692. {
  693. *pbstrValue = SysAllocString(V_BSTR(&vtValue));
  694. }
  695. // always return string, even if empty one (e.g. when media object is stale)
  696. if (SUCCEEDED(hr) && (*pbstrValue == NULL))
  697. {
  698. *pbstrValue = SysAllocString(L"");
  699. hr = S_OK;
  700. }
  701. return hr;
  702. }
  703. //------------------------------------------------------------------------
  704. HRESULT CWMPWrapper::AttachToWMP()
  705. {
  706. HRESULT hr = E_UNEXPECTED;
  707. if (_pHost)
  708. {
  709. CComDispatchDriver pwmpPlayer;
  710. hr = _pHost->getWMP(&pwmpPlayer);
  711. if (SUCCEEDED(hr) && pwmpPlayer)
  712. {
  713. // walk to WMP media object as signaled by requested type
  714. CComVariant vtMedia;
  715. hr = FetchWmpObject(pwmpPlayer, &vtMedia);
  716. if (SUCCEEDED(hr))
  717. {
  718. _pwmpWrapper = vtMedia;
  719. }
  720. }
  721. }
  722. return hr;
  723. }
  724. ///////////////////////////////////////////////////////////////////////////////
  725. ///////////////////////////////////////////////////////////////////////////////
  726. //
  727. // class CMediaItem
  728. //
  729. ///////////////////////////////////////////////////////////////////////////////
  730. ///////////////////////////////////////////////////////////////////////////////
  731. //------------------------------------------------------------------------
  732. CMediaItem::CMediaItem(CMediaBehavior* pHost)
  733. : CWMPWrapper(pHost),
  734. CImpIDispatch(LIBID_BrowseUI, 1, 0, IID_IMediaItem)
  735. {
  736. }
  737. //------------------------------------------------------------------------
  738. CMediaItem::~CMediaItem()
  739. {
  740. }
  741. //------------------------------------------------------------------------
  742. STDMETHODIMP CMediaItem::QueryInterface(REFIID riid, void **ppvObj)
  743. {
  744. if (ppvObj == NULL)
  745. return E_POINTER;
  746. if ( IsEqualIID(riid, IID_IUnknown)
  747. || IsEqualIID(riid, IID_IMediaItem))
  748. {
  749. *ppvObj = (IMediaItem*) this;
  750. }
  751. else if (IsEqualIID(riid, IID_IDispatch))
  752. {
  753. *ppvObj = (IDispatch*) this;
  754. }
  755. else
  756. {
  757. *ppvObj = NULL;
  758. return E_NOINTERFACE;
  759. }
  760. AddRef();
  761. return S_OK;
  762. }
  763. // *** IMediaItem
  764. //------------------------------------------------------------------------
  765. STDMETHODIMP CMediaItem::get_sourceURL(BSTR *pbstrSourceURL)
  766. {
  767. return _getStringProp(L"sourceURL", NULL, pbstrSourceURL);
  768. }
  769. //------------------------------------------------------------------------
  770. STDMETHODIMP CMediaItem::get_name(BSTR *pbstrName)
  771. {
  772. return _getStringProp(L"name", NULL, pbstrName);
  773. }
  774. //------------------------------------------------------------------------
  775. STDMETHODIMP CMediaItem::get_duration(double * pDuration)
  776. {
  777. if (pDuration == NULL)
  778. return E_POINTER;
  779. *pDuration = 0.0;
  780. CComVariant vtValue;
  781. HRESULT hr = _getVariantProp(L"duration", NULL, &vtValue);
  782. if (SUCCEEDED(hr) && (V_VT(&vtValue) == VT_R8))
  783. {
  784. *pDuration = V_R8(&vtValue);
  785. }
  786. return hr;
  787. }
  788. //------------------------------------------------------------------------
  789. STDMETHODIMP CMediaItem::get_attributeCount(long *plCount)
  790. {
  791. if (plCount == NULL)
  792. return E_POINTER;
  793. *plCount = 0;
  794. CComVariant vtValue;
  795. HRESULT hr = _getVariantProp(L"attributeCount", NULL, &vtValue);
  796. if (SUCCEEDED(hr) && (V_VT(&vtValue) == VT_I4))
  797. {
  798. *plCount = V_I4(&vtValue);
  799. }
  800. return hr;
  801. }
  802. //------------------------------------------------------------------------
  803. STDMETHODIMP CMediaItem::getAttributeName(long lIndex, BSTR *pbstrItemName)
  804. {
  805. CComVariant vtIndex = lIndex;
  806. return _getStringProp(L"getAttributeName", &vtIndex, pbstrItemName, TRUE);
  807. }
  808. //------------------------------------------------------------------------
  809. STDMETHODIMP CMediaItem::getItemInfo(BSTR bstrItemName, BSTR *pbstrVal)
  810. {
  811. CComVariant vtItemName = bstrItemName;
  812. return _getStringProp(L"getItemInfo", &vtItemName, pbstrVal, TRUE);
  813. }
  814. //------------------------------------------------------------------------
  815. HRESULT CMediaItem::FetchWmpObject(IDispatch *pdispWmpPlayer, OUT VARIANT *pvtWrapperObj)
  816. {
  817. CComDispatchDriver pwmpPlayer;
  818. pwmpPlayer = pdispWmpPlayer;
  819. return pwmpPlayer.GetPropertyByName(L"currentMedia", pvtWrapperObj);
  820. }
  821. //////////////////////////////////////////////////////////////////
  822. ///////////////////////////////////////////////////////////////////////////////
  823. //
  824. // class CMediaItemNext
  825. //
  826. ///////////////////////////////////////////////////////////////////////////////
  827. ///////////////////////////////////////////////////////////////////////////////
  828. //------------------------------------------------------------------------
  829. CMediaItemNext::CMediaItemNext(CMediaBehavior* pHost)
  830. : CMediaItem(pHost)
  831. {
  832. }
  833. //------------------------------------------------------------------------
  834. CMediaItemNext::~CMediaItemNext()
  835. {
  836. }
  837. //------------------------------------------------------------------------
  838. HRESULT CMediaItemNext::FetchWmpObject(IDispatch *pdispWmpPlayer, OUT VARIANT *pvtWrapperObj)
  839. {
  840. if (!_pHost)
  841. {
  842. return E_UNEXPECTED;
  843. }
  844. CComDispatchDriver pwmpPlayer;
  845. pwmpPlayer = pdispWmpPlayer;
  846. HRESULT hr = E_UNEXPECTED;
  847. CComVariant vtCurrPlayList;
  848. hr = pwmpPlayer.GetPropertyByName(L"currentPlaylist", &vtCurrPlayList);
  849. if (SUCCEEDED(hr))
  850. {
  851. CComDispatchDriverEx pwmpCurrPlayList;
  852. pwmpCurrPlayList = vtCurrPlayList;
  853. // what's the index of the current item in play?
  854. CComPtr<IMediaBarPlayer> pMediaPlayer;
  855. LONG cnt = 0;
  856. LONG currIndex = 0;
  857. hr = _pHost->getPlayListIndex(&currIndex, &cnt);
  858. if (SUCCEEDED(hr))
  859. {
  860. if (currIndex + 1 < cnt)
  861. {
  862. CComVariant vtNext = currIndex + 1;
  863. return pwmpCurrPlayList.GetPropertyByName1(L"item", &vtNext, pvtWrapperObj);
  864. }
  865. else
  866. {
  867. return E_UNEXPECTED;
  868. }
  869. }
  870. }
  871. return hr;
  872. }
  873. ///////////////////////////////////////////////////////////////////////////////
  874. ///////////////////////////////////////////////////////////////////////////////
  875. //
  876. // class CPlaylistInfo
  877. //
  878. ///////////////////////////////////////////////////////////////////////////////
  879. ///////////////////////////////////////////////////////////////////////////////
  880. //------------------------------------------------------------------------
  881. CPlaylistInfo::CPlaylistInfo(CMediaBehavior* pHost)
  882. : CWMPWrapper(pHost),
  883. CImpIDispatch(LIBID_BrowseUI, 1, 0, IID_IPlaylistInfo)
  884. {
  885. }
  886. //------------------------------------------------------------------------
  887. CPlaylistInfo::~CPlaylistInfo()
  888. {
  889. }
  890. //------------------------------------------------------------------------
  891. STDMETHODIMP CPlaylistInfo::QueryInterface(REFIID riid, void **ppvObj)
  892. {
  893. if (ppvObj == NULL)
  894. return E_POINTER;
  895. if ( IsEqualIID(riid, IID_IUnknown)
  896. || IsEqualIID(riid, IID_IPlaylistInfo))
  897. {
  898. *ppvObj = (IPlaylistInfo*) this;
  899. }
  900. else if (IsEqualIID(riid, IID_IDispatch))
  901. {
  902. *ppvObj = (IDispatch*) this;
  903. }
  904. else
  905. {
  906. *ppvObj = NULL;
  907. return E_NOINTERFACE;
  908. }
  909. AddRef();
  910. return S_OK;
  911. }
  912. // *** IPlaylistInfo
  913. //------------------------------------------------------------------------
  914. //------------------------------------------------------------------------
  915. STDMETHODIMP CPlaylistInfo::get_name(BSTR *pbstrName)
  916. {
  917. return _getStringProp(L"name", NULL, pbstrName);
  918. }
  919. //------------------------------------------------------------------------
  920. STDMETHODIMP CPlaylistInfo::get_attributeCount(long *plCount)
  921. {
  922. if (plCount == NULL)
  923. return E_POINTER;
  924. *plCount = 0;
  925. CComVariant vtValue;
  926. HRESULT hr = _getVariantProp(L"attributeCount", NULL, &vtValue);
  927. if (SUCCEEDED(hr) && (V_VT(&vtValue) == VT_I4))
  928. {
  929. *plCount = V_I4(&vtValue);
  930. }
  931. return hr;
  932. }
  933. //------------------------------------------------------------------------
  934. STDMETHODIMP CPlaylistInfo::getAttributeName(long lIndex, BSTR *pbstrItemName)
  935. {
  936. CComVariant vtIndex = lIndex;
  937. return _getStringProp(L"attributeName", &vtIndex, pbstrItemName);
  938. }
  939. //------------------------------------------------------------------------
  940. STDMETHODIMP CPlaylistInfo::getItemInfo(BSTR bstrItemName, BSTR *pbstrVal)
  941. {
  942. CComVariant vtItemName = bstrItemName;
  943. return _getStringProp(L"getItemInfo", &vtItemName, pbstrVal, TRUE);
  944. }
  945. //------------------------------------------------------------------------
  946. HRESULT CPlaylistInfo::FetchWmpObject(IDispatch *pdispWmpPlayer, OUT VARIANT *pvtWrapperObj)
  947. {
  948. CComDispatchDriver pwmpPlayer;
  949. pwmpPlayer = pdispWmpPlayer;
  950. return pwmpPlayer.GetPropertyByName(L"currentPlaylist", pvtWrapperObj);
  951. }