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
31 KiB
1097 lines
31 KiB
//------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 2001
|
|
//
|
|
// File: mbBehave.cpp
|
|
//
|
|
// Contents: mediaBar player behavior
|
|
//
|
|
// Classes: CMediaBehavior
|
|
//
|
|
//------------------------------------------------------------------------
|
|
|
|
#include "priv.h"
|
|
#define INITGUID // pull in additional declaration for private mediabar IIDs
|
|
#include "initguid.h"
|
|
#include "mbBehave.h"
|
|
#undef INITGUID
|
|
#include "mediaBand.h"
|
|
#include "mediautil.h"
|
|
#include "varutil.h"
|
|
#include <mluisupp.h>
|
|
#include "resource.h"
|
|
|
|
//================================================================================================
|
|
// CMediaBehavior
|
|
//================================================================================================
|
|
|
|
#define NO_COOKIE -1
|
|
|
|
|
|
// event names fired from this behavior:
|
|
// NOTE: need to match the enums in the mbBehave.h with this array!!!
|
|
struct _eventInfo {
|
|
LONG levtCookie;
|
|
LPWSTR pwszName;
|
|
} s_behaviorEvents[] =
|
|
{
|
|
NO_COOKIE, L"OnOpenStateChange",
|
|
NO_COOKIE, L"OnPlayStateChange",
|
|
NO_COOKIE, L"OnShow",
|
|
NO_COOKIE, L"OnHide",
|
|
};
|
|
|
|
#ifndef WMPCOREEVENT_BASE
|
|
// ISSUE/010430/davidjen should be pulled in from wmp.idl, but this file is not part of source tree
|
|
#define INITGUID // define GUID, not only declare it
|
|
#include "initguid.h"
|
|
DEFINE_GUID(DIID__WMPOCXEvents,0x6BF52A51,0x394A,0x11d3,0xB1,0x53,0x00,0xC0,0x4F,0x79,0xFA,0xA6);
|
|
#define WMPCOREEVENT_BASE 5000
|
|
#define DISPID_WMPCOREEVENT_OPENSTATECHANGE (WMPCOREEVENT_BASE + 1)
|
|
#define WMPCOREEVENT_CONTROL_BASE 5100
|
|
#define DISPID_WMPCOREEVENT_PLAYSTATECHANGE (WMPCOREEVENT_CONTROL_BASE + 1)
|
|
#undef INITGUID
|
|
#endif
|
|
|
|
|
|
|
|
// class factories
|
|
//------------------------------------------------------------------------
|
|
CMediaBehavior *
|
|
CMediaBehavior_CreateInstance(CMediaBand* pHost)
|
|
{
|
|
return new CMediaBehavior(pHost);
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
CMediaItem *
|
|
CMediaItem_CreateInstance(CMediaBehavior* pHost)
|
|
{
|
|
return new CMediaItem(pHost);
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
CMediaItemNext *
|
|
CMediaItemNext_CreateInstance(CMediaBehavior* pHost)
|
|
{
|
|
return new CMediaItemNext(pHost);
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
CPlaylistInfo *
|
|
CPlaylistInfo_CreateInstance(CMediaBehavior* pHost)
|
|
{
|
|
return new CPlaylistInfo(pHost);
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// class CMediaBehavior
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
//------------------------------------------------------------------------
|
|
CMediaBehavior::CMediaBehavior(CMediaBand* pHost)
|
|
: CImpIDispatch(LIBID_BrowseUI, 1, 0, IID_IMediaBehavior),
|
|
_cRef(0),
|
|
_dwcpCookie(0),
|
|
_fDisabledUI(FALSE),
|
|
_fPlaying(FALSE)
|
|
{
|
|
ASSERT(pHost);
|
|
_pHost = pHost;
|
|
if (_pHost)
|
|
{
|
|
_pHost->AddRef();
|
|
HRESULT hr = _pHost->addProxy((IContentProxy*)this);
|
|
ASSERT(SUCCEEDED(hr));
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
CMediaBehavior::~CMediaBehavior()
|
|
{
|
|
Detach(); // to be sure...
|
|
if (_pHost)
|
|
_pHost->Release();
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
STDMETHODIMP CMediaBehavior::QueryInterface(REFIID riid, void **ppv)
|
|
{
|
|
static const QITAB qit[] =
|
|
{
|
|
QITABENT(CMediaBehavior, IElementBehavior),
|
|
QITABENT(CMediaBehavior, IMediaBehavior),
|
|
QITABENT(CMediaBehavior, IDispatch),
|
|
QITABENTMULTI2(CMediaBehavior, DIID__WMPOCXEvents, IDispatch),
|
|
QITABENT(CMediaBehavior, IContentProxy),
|
|
QITABENT(CMediaBehavior, IMediaBehaviorContentProxy),
|
|
{ 0 },
|
|
};
|
|
return QISearch(this, qit, riid, ppv);
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
STDMETHODIMP CMediaBehavior::Detach(void)
|
|
{
|
|
_ConnectToWmpEvents(FALSE);
|
|
|
|
// detach from behavior site
|
|
if (_pHost)
|
|
{
|
|
_pHost->removeProxy(SAFECAST(this, IContentProxy*)); // optimize: _pHost saves ptr as IContentProxy, this saves a QI
|
|
_pHost->Release();
|
|
_pHost = NULL;
|
|
}
|
|
_fPlaying = FALSE;
|
|
|
|
if (_apMediaItems != NULL)
|
|
{
|
|
int cnt = _apMediaItems.GetPtrCount();
|
|
for (int i = 0; i < cnt; i++)
|
|
{
|
|
CMediaItem* pItem = _apMediaItems.GetPtr(i);
|
|
if (pItem)
|
|
pItem->Release();
|
|
}
|
|
_apMediaItems.Destroy();
|
|
}
|
|
|
|
_pBehaviorSite.Release();
|
|
_pBehaviorSiteOM.Release();
|
|
for (int i = 0; i < ARRAYSIZE(s_behaviorEvents); i++)
|
|
{
|
|
s_behaviorEvents[i].levtCookie = NO_COOKIE;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
STDMETHODIMP CMediaBehavior::Init(IElementBehaviorSite* pBehaviorSite)
|
|
{
|
|
ASSERT(pBehaviorSite);
|
|
if (pBehaviorSite == NULL) return E_POINTER;
|
|
|
|
_pBehaviorSite = pBehaviorSite;
|
|
|
|
pBehaviorSite->QueryInterface(IID_PPV_ARG(IElementBehaviorSiteOM, &_pBehaviorSiteOM));
|
|
ASSERT(_pBehaviorSiteOM != NULL);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
STDMETHODIMP CMediaBehavior::Notify(LONG lEvent, VARIANT* pVar)
|
|
{
|
|
// ISSUE/000923/davidjen
|
|
// these enums require behavior.idl; this idl is only available in inetcore,
|
|
// might have to be moved to shell/published or mergedcomponents
|
|
/*
|
|
switch (lEvent) {
|
|
case BEHAVIOREVENT_CONTENTCHANGE:
|
|
break;
|
|
case BEHAVIOREVENT_DOCUMENTREADY:
|
|
break;
|
|
}
|
|
*/
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
// *** IDispatch ***
|
|
//------------------------------------------------------------------------
|
|
STDMETHODIMP CMediaBehavior::Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo, UINT * puArgErr)
|
|
{
|
|
if (!_ProcessEvent(dispidMember, pdispparams->cArgs, pdispparams->rgvarg))
|
|
{
|
|
return CImpIDispatch::Invoke(dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
BOOL CMediaBehavior::_ProcessEvent(DISPID dispid, long lCount, VARIANT varParams[])
|
|
{
|
|
BOOL fHandled = FALSE;
|
|
switch (dispid)
|
|
{
|
|
case DISPID_WMPCOREEVENT_PLAYSTATECHANGE:
|
|
ASSERT(lCount == 1);
|
|
ASSERT(V_VT(&varParams[0]) == VT_I4);
|
|
fireEvent(OnPlayStateChange);
|
|
fHandled = TRUE;
|
|
break;
|
|
case DISPID_WMPCOREEVENT_OPENSTATECHANGE:
|
|
ASSERT(lCount == 1);
|
|
ASSERT(V_VT(&varParams[0]) == VT_I4);
|
|
fireEvent(OnOpenStateChange);
|
|
fHandled = TRUE;
|
|
break;
|
|
default:
|
|
fHandled = FALSE;
|
|
break;
|
|
}
|
|
return fHandled;
|
|
}
|
|
|
|
|
|
// *** IMediaBehavior ***
|
|
//------------------------------------------------------------------------
|
|
STDMETHODIMP CMediaBehavior::playURL(BSTR bstrURL, BSTR bstrMIME)
|
|
{
|
|
if (!_pHost)
|
|
{
|
|
return E_UNEXPECTED;
|
|
}
|
|
_fPlaying = TRUE;
|
|
_pHost->playURL(bstrURL, bstrMIME);
|
|
return S_OK;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
STDMETHODIMP CMediaBehavior::stop()
|
|
{
|
|
if (!_pHost)
|
|
{
|
|
return E_UNEXPECTED;
|
|
}
|
|
return IUnknown_Exec(SAFECAST(_pHost, IMediaBar*), &CLSID_MediaBand, FCIDM_MEDIABAND_STOP, 0, NULL, NULL);
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
STDMETHODIMP CMediaBehavior::playNext()
|
|
{
|
|
if (!_pHost)
|
|
{
|
|
return E_UNEXPECTED;
|
|
}
|
|
return IUnknown_Exec(SAFECAST(_pHost, IMediaBar*), &CLSID_MediaBand, FCIDM_MEDIABAND_NEXT, 0, NULL, NULL);
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
STDMETHODIMP CMediaBehavior::get_currentItem(IMediaItem **ppMediaItem)
|
|
{
|
|
if (ppMediaItem == NULL)
|
|
return E_POINTER;
|
|
*ppMediaItem = NULL;
|
|
|
|
HRESULT hr = S_OK;
|
|
if (_apMediaItems == NULL) {
|
|
_apMediaItems.Create(2);
|
|
}
|
|
if (_apMediaItems == NULL)
|
|
return E_OUTOFMEMORY;
|
|
|
|
CMediaItem *pItem = CMediaItem_CreateInstance(this);
|
|
if (pItem)
|
|
{
|
|
pItem->AddRef(); // keep object alive with ref count >= 1
|
|
hr = pItem->AttachToWMP();
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pItem->QueryInterface(IID_PPV_ARG(IMediaItem, ppMediaItem));
|
|
// pItem->AddRef();
|
|
// _apMediaItems.AppendPtr(pItem); // keep a ref for us
|
|
}
|
|
pItem->Release();
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
STDMETHODIMP CMediaBehavior::get_nextItem(IMediaItem **ppMediaItem)
|
|
{
|
|
if (ppMediaItem == NULL)
|
|
return E_POINTER;
|
|
*ppMediaItem = NULL;
|
|
|
|
HRESULT hr = S_OK;
|
|
if (_apMediaItems == NULL) {
|
|
_apMediaItems.Create(2);
|
|
}
|
|
if (_apMediaItems == NULL)
|
|
return E_OUTOFMEMORY;
|
|
|
|
CMediaItemNext *pItem = CMediaItemNext_CreateInstance(this);
|
|
if (pItem)
|
|
{
|
|
pItem->AddRef(); // keep object alive with ref count >= 1
|
|
hr = pItem->AttachToWMP();
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pItem->QueryInterface(IID_PPV_ARG(IMediaItem, ppMediaItem));
|
|
// pItem->AddRef();
|
|
// _apMediaItems.AppendPtr(pItem); // keep a ref for us
|
|
}
|
|
pItem->Release();
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
STDMETHODIMP CMediaBehavior::get_playlistInfo(IPlaylistInfo **ppPlaylistInfo)
|
|
{
|
|
if (ppPlaylistInfo == NULL)
|
|
return E_POINTER;
|
|
*ppPlaylistInfo = NULL;
|
|
|
|
HRESULT hr = S_OK;
|
|
if (_apMediaItems == NULL) {
|
|
_apMediaItems.Create(2);
|
|
}
|
|
if (_apMediaItems == NULL)
|
|
return E_OUTOFMEMORY;
|
|
|
|
CPlaylistInfo *pInfo = CPlaylistInfo_CreateInstance(this);
|
|
if (pInfo)
|
|
{
|
|
pInfo->AddRef(); // keep object alive with ref count >= 1
|
|
hr = pInfo->AttachToWMP();
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pInfo->QueryInterface(IID_PPV_ARG(IPlaylistInfo, ppPlaylistInfo));
|
|
// pItem->AddRef();
|
|
// _apMediaItems.AppendPtr(pInfo); // keep a ref for us
|
|
}
|
|
pInfo->Release();
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
STDMETHODIMP CMediaBehavior::get_hasNextItem(VARIANT_BOOL *pfhasNext)
|
|
{
|
|
if (pfhasNext == NULL)
|
|
{
|
|
return E_POINTER;
|
|
}
|
|
*pfhasNext = VARIANT_FALSE;
|
|
if (!_pHost)
|
|
{
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
LONG currTrack = 0;
|
|
LONG cntTracks = 0;
|
|
HRESULT hr = getPlayListIndex(&currTrack, &cntTracks);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
*pfhasNext = ((currTrack >= 0) && (currTrack < cntTracks - 1)) ? VARIANT_TRUE : VARIANT_FALSE;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
STDMETHODIMP CMediaBehavior::get_playState(mbPlayState *pps)
|
|
{
|
|
if (pps == NULL)
|
|
return E_POINTER;
|
|
*pps = mbpsUndefined;
|
|
|
|
CComDispatchDriver pwmpPlayer;
|
|
HRESULT hr = getWMP(&pwmpPlayer);
|
|
if (FAILED(hr) || !pwmpPlayer)
|
|
{
|
|
// player not created yet, state undefined
|
|
*pps = mbpsUndefined;
|
|
return S_OK;
|
|
}
|
|
|
|
CComVariant vtPlayState;
|
|
hr = pwmpPlayer.GetPropertyByName(L"playState", &vtPlayState);
|
|
if (SUCCEEDED(hr) && (V_VT(&vtPlayState) == VT_I4))
|
|
{
|
|
*pps = (mbPlayState) V_I4(&vtPlayState);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
STDMETHODIMP CMediaBehavior::get_openState(mbOpenState *pos)
|
|
{
|
|
if (pos == NULL)
|
|
return E_POINTER;
|
|
*pos = mbosUndefined;
|
|
|
|
CComDispatchDriver pwmpPlayer;
|
|
HRESULT hr = getWMP(&pwmpPlayer);
|
|
if (FAILED(hr) || !pwmpPlayer)
|
|
{
|
|
// player not created yet, state undefined
|
|
*pos = mbosUndefined;
|
|
return S_OK;
|
|
}
|
|
|
|
CComVariant vtOpenState;
|
|
hr = pwmpPlayer.GetPropertyByName(L"openState", &vtOpenState);
|
|
if (SUCCEEDED(hr) && (V_VT(&vtOpenState) == VT_I4))
|
|
{
|
|
*pos = (mbOpenState) V_I4(&vtOpenState);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
STDMETHODIMP CMediaBehavior::get_enabled(VARIANT_BOOL *pbEnabled)
|
|
{
|
|
if (pbEnabled == NULL)
|
|
return E_POINTER;
|
|
*pbEnabled = VARIANT_FALSE;
|
|
|
|
CComDispatchDriver pwmpPlayer;
|
|
HRESULT hr = getWMP(&pwmpPlayer);
|
|
if (FAILED(hr) || !pwmpPlayer)
|
|
{
|
|
// player not created yet, state undefined
|
|
*pbEnabled = VARIANT_FALSE;
|
|
return S_FALSE;
|
|
}
|
|
|
|
CComVariant vtEnabled;
|
|
hr = pwmpPlayer.GetPropertyByName(L"enabled", &vtEnabled);
|
|
if (SUCCEEDED(hr) && (V_VT(&vtEnabled) == VT_BOOL))
|
|
{
|
|
*pbEnabled = V_BOOL(&vtEnabled);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
STDMETHODIMP CMediaBehavior::put_enabled(VARIANT_BOOL bEnabled)
|
|
{
|
|
CComDispatchDriver pwmpPlayer;
|
|
HRESULT hr = getWMP(&pwmpPlayer);
|
|
if (FAILED(hr) || !pwmpPlayer)
|
|
{
|
|
// player not created yet, fire exception to let scrip know it has no control
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
CComVariant vtEnabled = bEnabled;
|
|
return pwmpPlayer.PutPropertyByName(L"enabled", &vtEnabled);
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
STDMETHODIMP CMediaBehavior::get_disabledUI(VARIANT_BOOL *pbDisabled)
|
|
{
|
|
if (pbDisabled == NULL)
|
|
return E_POINTER;
|
|
*pbDisabled = _fDisabledUI ? VARIANT_TRUE : VARIANT_FALSE;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
STDMETHODIMP CMediaBehavior::put_disabledUI(VARIANT_BOOL bDisable)
|
|
{
|
|
_fDisabledUI = bDisable;
|
|
// tell mediaband
|
|
if (_pHost)
|
|
{
|
|
_pHost->OnDisableUIChanged(_fDisabledUI);
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//
|
|
// *** IMediaBehaviorContentProxy ***
|
|
//------------------------------------------------------------------------
|
|
STDMETHODIMP CMediaBehavior::OnCreatedPlayer(void)
|
|
{
|
|
return _ConnectToWmpEvents(TRUE);
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
STDMETHODIMP CMediaBehavior::fireEvent(enum contentProxyEvent event)
|
|
{
|
|
ASSERT(_pBehaviorSiteOM != NULL); // called too early, must have received Init() call from Trident first!
|
|
if (!_pBehaviorSiteOM)
|
|
return E_UNEXPECTED;
|
|
|
|
if ((event < 0) || (event >= ARRAYSIZE(s_behaviorEvents)))
|
|
return E_INVALIDARG;
|
|
|
|
struct _eventInfo *pEvtInfo = &s_behaviorEvents[event];
|
|
|
|
HRESULT hr = S_OK;
|
|
// don't have cookie yet, need to register event first!
|
|
if (pEvtInfo->levtCookie == NO_COOKIE)
|
|
{
|
|
// register event with behavior site
|
|
hr = _pBehaviorSiteOM->RegisterEvent(pEvtInfo->pwszName, 0, &pEvtInfo->levtCookie);
|
|
ASSERT(SUCCEEDED(hr));
|
|
if (FAILED(hr))
|
|
return hr;
|
|
}
|
|
if (pEvtInfo->levtCookie == NO_COOKIE)
|
|
return E_UNEXPECTED;
|
|
|
|
CComPtr<IHTMLEventObj> pEvt;
|
|
hr = _pBehaviorSiteOM->CreateEventObject(&pEvt);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
// fire into script:
|
|
return _pBehaviorSiteOM->FireEvent(pEvtInfo->levtCookie, pEvt);
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
STDMETHODIMP CMediaBehavior::detachPlayer(void)
|
|
{
|
|
return _ConnectToWmpEvents(FALSE);
|
|
}
|
|
|
|
// *** IMediaBehaviorContentProxy ***
|
|
//------------------------------------------------------------------------
|
|
STDMETHODIMP CMediaBehavior::OnUserOverrideDisableUI()
|
|
{
|
|
return put_disabledUI(VARIANT_FALSE);
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
STDMETHODIMP CMediaBehavior::IsDisableUIRequested(BOOL *pfRequested)
|
|
{
|
|
if (!pfRequested)
|
|
{
|
|
return E_POINTER;
|
|
}
|
|
*pfRequested = _fDisabledUI;
|
|
return S_OK;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
STDMETHODIMP CMediaBehavior::IsNextEnabled(BOOL *pfEnabled)
|
|
{
|
|
if (!pfEnabled)
|
|
{
|
|
return E_POINTER;
|
|
}
|
|
*pfEnabled = FALSE;
|
|
|
|
CComDispatchDriverEx pwmpPlayer;
|
|
HRESULT hr = getWMP(&pwmpPlayer);
|
|
if (SUCCEEDED(hr) && pwmpPlayer)
|
|
{
|
|
CComVariant vtControls;
|
|
hr = pwmpPlayer.GetPropertyByName(L"controls", &vtControls);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
CComDispatchDriverEx pwmpControls;
|
|
pwmpControls = vtControls;
|
|
|
|
CComVariant vtNext = "Next";
|
|
CComVariant vtEnabled;
|
|
hr = pwmpControls.GetPropertyByName1(L"isAvailable", &vtNext, &vtEnabled);
|
|
if (SUCCEEDED(hr) && (V_VT(&vtEnabled) == VT_BOOL))
|
|
{
|
|
*pfEnabled = (V_BOOL(&vtEnabled) == VARIANT_TRUE);
|
|
}
|
|
}
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
HRESULT CMediaBehavior::getWMP(IDispatch **ppPlayer)
|
|
{
|
|
if (ppPlayer == NULL)
|
|
return E_POINTER;
|
|
*ppPlayer = NULL;
|
|
if (!CMediaBarUtil::IsWMP7OrGreaterCapable() || !_pHost)
|
|
{
|
|
return E_UNEXPECTED;
|
|
}
|
|
if (!_fPlaying)
|
|
{
|
|
return E_ACCESSDENIED;
|
|
}
|
|
|
|
HRESULT hr = E_UNEXPECTED;
|
|
CComPtr<IUnknown> pMediaPlayer;
|
|
hr = _pHost->getMediaPlayer(&pMediaPlayer);
|
|
// getMediaPlayer can return NULL and S_FALSE if player isn't loaded yet!
|
|
if (SUCCEEDED(hr) && pMediaPlayer)
|
|
{
|
|
CComQIPtr<ITIMEMediaElement, &IID_ITIMEMediaElement> pMediaElem = pMediaPlayer;
|
|
if (pMediaElem)
|
|
{
|
|
return pMediaElem->get_playerObject(ppPlayer);
|
|
}
|
|
else
|
|
{
|
|
hr = E_NOINTERFACE;
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
HRESULT CMediaBehavior::getPlayListIndex(LONG *plIndex, LONG *plCount)
|
|
{
|
|
if (!_pHost)
|
|
{
|
|
return E_UNEXPECTED;
|
|
}
|
|
CComPtr<IUnknown> pMediaPlayer;
|
|
HRESULT hr = _pHost->getMediaPlayer(&pMediaPlayer);
|
|
// getMediaPlayer can return NULL and S_FALSE if player isn't loaded yet!
|
|
if (SUCCEEDED(hr) && pMediaPlayer)
|
|
{
|
|
CComQIPtr<ITIMEMediaElement, &IID_ITIMEMediaElement> pMediaElem = pMediaPlayer;
|
|
if (pMediaElem)
|
|
{
|
|
CComPtr<ITIMEPlayList> pPlayList;
|
|
if (SUCCEEDED(pMediaElem->get_playList(&pPlayList)) && pPlayList)
|
|
{
|
|
// current track index
|
|
if (plIndex)
|
|
{
|
|
CComPtr<ITIMEPlayItem> pPlayItem;
|
|
if (SUCCEEDED(pPlayList->get_activeTrack(&pPlayItem)) && pPlayItem)
|
|
{
|
|
hr = pPlayItem->get_index(plIndex);
|
|
}
|
|
}
|
|
// number of tracks in playlist
|
|
if (plCount)
|
|
{
|
|
hr = pPlayList->get_length(plCount);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
HRESULT CMediaBehavior::_ConnectToWmpEvents(BOOL fConnect)
|
|
{
|
|
if ( (fConnect && (_dwcpCookie != 0))
|
|
|| (!fConnect && (_dwcpCookie == 0))
|
|
|| !_pHost)
|
|
{
|
|
return S_FALSE; // no change in connection or no host
|
|
}
|
|
|
|
CComPtr<IDispatch> pwmpPlayer;
|
|
HRESULT hr = getWMP(&pwmpPlayer);
|
|
if (SUCCEEDED(hr) && pwmpPlayer)
|
|
{
|
|
return ConnectToConnectionPoint(SAFECAST(this, IDispatch*),
|
|
DIID__WMPOCXEvents, fConnect, pwmpPlayer, &_dwcpCookie, NULL);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// class CWMPWrapper
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
//------------------------------------------------------------------------
|
|
CWMPWrapper::CWMPWrapper(CMediaBehavior* pHost)
|
|
: _cRef(0),
|
|
_fStale(FALSE)
|
|
{
|
|
ASSERT(pHost);
|
|
_pHost = pHost;
|
|
if (_pHost)
|
|
_pHost->AddRef();
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
CWMPWrapper::~CWMPWrapper()
|
|
{
|
|
if (_pHost)
|
|
_pHost->Release();
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
HRESULT CWMPWrapper::_getVariantProp(LPCOLESTR pwszPropName, VARIANT *pvtParam, VARIANT *pvtValue, BOOL fCallMethod)
|
|
{
|
|
if (pvtValue == NULL)
|
|
return E_POINTER;
|
|
|
|
HRESULT hr = S_FALSE;
|
|
VariantInit(pvtValue);
|
|
if (!_fStale && _pwmpWrapper)
|
|
{
|
|
if (fCallMethod)
|
|
{
|
|
if (pvtParam != NULL)
|
|
{
|
|
hr = _pwmpWrapper.Invoke1(pwszPropName, pvtParam, pvtValue);
|
|
}
|
|
else
|
|
{
|
|
hr = _pwmpWrapper.Invoke0(pwszPropName, pvtValue);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (pvtParam != NULL)
|
|
{
|
|
hr = _pwmpWrapper.GetPropertyByName1(pwszPropName, pvtParam, pvtValue);
|
|
}
|
|
else
|
|
{
|
|
hr = _pwmpWrapper.GetPropertyByName(pwszPropName, pvtValue);
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
HRESULT CWMPWrapper::_getStringProp(LPCOLESTR pwszPropName, VARIANT *pvtParam, OUT BSTR *pbstrValue, BOOL fCallMethod)
|
|
{
|
|
if (pbstrValue == NULL)
|
|
return E_POINTER;
|
|
*pbstrValue = NULL;
|
|
|
|
CComVariant vtValue;
|
|
HRESULT hr = _getVariantProp(pwszPropName, pvtParam, &vtValue, fCallMethod);
|
|
if (SUCCEEDED(hr) && (V_VT(&vtValue) == VT_BSTR))
|
|
{
|
|
*pbstrValue = SysAllocString(V_BSTR(&vtValue));
|
|
}
|
|
|
|
// always return string, even if empty one (e.g. when media object is stale)
|
|
if (SUCCEEDED(hr) && (*pbstrValue == NULL))
|
|
{
|
|
*pbstrValue = SysAllocString(L"");
|
|
hr = S_OK;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
HRESULT CWMPWrapper::AttachToWMP()
|
|
{
|
|
HRESULT hr = E_UNEXPECTED;
|
|
if (_pHost)
|
|
{
|
|
CComDispatchDriver pwmpPlayer;
|
|
hr = _pHost->getWMP(&pwmpPlayer);
|
|
if (SUCCEEDED(hr) && pwmpPlayer)
|
|
{
|
|
// walk to WMP media object as signaled by requested type
|
|
CComVariant vtMedia;
|
|
hr = FetchWmpObject(pwmpPlayer, &vtMedia);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
_pwmpWrapper = vtMedia;
|
|
}
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// class CMediaItem
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
//------------------------------------------------------------------------
|
|
CMediaItem::CMediaItem(CMediaBehavior* pHost)
|
|
: CWMPWrapper(pHost),
|
|
CImpIDispatch(LIBID_BrowseUI, 1, 0, IID_IMediaItem)
|
|
{
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
CMediaItem::~CMediaItem()
|
|
{
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
STDMETHODIMP CMediaItem::QueryInterface(REFIID riid, void **ppvObj)
|
|
{
|
|
if (ppvObj == NULL)
|
|
return E_POINTER;
|
|
|
|
if ( IsEqualIID(riid, IID_IUnknown)
|
|
|| IsEqualIID(riid, IID_IMediaItem))
|
|
{
|
|
*ppvObj = (IMediaItem*) this;
|
|
}
|
|
else if (IsEqualIID(riid, IID_IDispatch))
|
|
{
|
|
*ppvObj = (IDispatch*) this;
|
|
}
|
|
else
|
|
{
|
|
*ppvObj = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
// *** IMediaItem
|
|
//------------------------------------------------------------------------
|
|
STDMETHODIMP CMediaItem::get_sourceURL(BSTR *pbstrSourceURL)
|
|
{
|
|
return _getStringProp(L"sourceURL", NULL, pbstrSourceURL);
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
STDMETHODIMP CMediaItem::get_name(BSTR *pbstrName)
|
|
{
|
|
return _getStringProp(L"name", NULL, pbstrName);
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
STDMETHODIMP CMediaItem::get_duration(double * pDuration)
|
|
{
|
|
if (pDuration == NULL)
|
|
return E_POINTER;
|
|
*pDuration = 0.0;
|
|
|
|
CComVariant vtValue;
|
|
HRESULT hr = _getVariantProp(L"duration", NULL, &vtValue);
|
|
if (SUCCEEDED(hr) && (V_VT(&vtValue) == VT_R8))
|
|
{
|
|
*pDuration = V_R8(&vtValue);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
STDMETHODIMP CMediaItem::get_attributeCount(long *plCount)
|
|
{
|
|
if (plCount == NULL)
|
|
return E_POINTER;
|
|
*plCount = 0;
|
|
|
|
CComVariant vtValue;
|
|
HRESULT hr = _getVariantProp(L"attributeCount", NULL, &vtValue);
|
|
if (SUCCEEDED(hr) && (V_VT(&vtValue) == VT_I4))
|
|
{
|
|
*plCount = V_I4(&vtValue);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
STDMETHODIMP CMediaItem::getAttributeName(long lIndex, BSTR *pbstrItemName)
|
|
{
|
|
CComVariant vtIndex = lIndex;
|
|
return _getStringProp(L"getAttributeName", &vtIndex, pbstrItemName, TRUE);
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
STDMETHODIMP CMediaItem::getItemInfo(BSTR bstrItemName, BSTR *pbstrVal)
|
|
{
|
|
CComVariant vtItemName = bstrItemName;
|
|
return _getStringProp(L"getItemInfo", &vtItemName, pbstrVal, TRUE);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
HRESULT CMediaItem::FetchWmpObject(IDispatch *pdispWmpPlayer, OUT VARIANT *pvtWrapperObj)
|
|
{
|
|
CComDispatchDriver pwmpPlayer;
|
|
pwmpPlayer = pdispWmpPlayer;
|
|
return pwmpPlayer.GetPropertyByName(L"currentMedia", pvtWrapperObj);
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// class CMediaItemNext
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
//------------------------------------------------------------------------
|
|
CMediaItemNext::CMediaItemNext(CMediaBehavior* pHost)
|
|
: CMediaItem(pHost)
|
|
{
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
CMediaItemNext::~CMediaItemNext()
|
|
{
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
HRESULT CMediaItemNext::FetchWmpObject(IDispatch *pdispWmpPlayer, OUT VARIANT *pvtWrapperObj)
|
|
{
|
|
if (!_pHost)
|
|
{
|
|
return E_UNEXPECTED;
|
|
}
|
|
CComDispatchDriver pwmpPlayer;
|
|
pwmpPlayer = pdispWmpPlayer;
|
|
|
|
HRESULT hr = E_UNEXPECTED;
|
|
CComVariant vtCurrPlayList;
|
|
hr = pwmpPlayer.GetPropertyByName(L"currentPlaylist", &vtCurrPlayList);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
CComDispatchDriverEx pwmpCurrPlayList;
|
|
pwmpCurrPlayList = vtCurrPlayList;
|
|
|
|
// what's the index of the current item in play?
|
|
CComPtr<IMediaBarPlayer> pMediaPlayer;
|
|
LONG cnt = 0;
|
|
LONG currIndex = 0;
|
|
hr = _pHost->getPlayListIndex(&currIndex, &cnt);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (currIndex + 1 < cnt)
|
|
{
|
|
CComVariant vtNext = currIndex + 1;
|
|
return pwmpCurrPlayList.GetPropertyByName1(L"item", &vtNext, pvtWrapperObj);
|
|
}
|
|
else
|
|
{
|
|
return E_UNEXPECTED;
|
|
}
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// class CPlaylistInfo
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
//------------------------------------------------------------------------
|
|
CPlaylistInfo::CPlaylistInfo(CMediaBehavior* pHost)
|
|
: CWMPWrapper(pHost),
|
|
CImpIDispatch(LIBID_BrowseUI, 1, 0, IID_IPlaylistInfo)
|
|
{
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
CPlaylistInfo::~CPlaylistInfo()
|
|
{
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
STDMETHODIMP CPlaylistInfo::QueryInterface(REFIID riid, void **ppvObj)
|
|
{
|
|
if (ppvObj == NULL)
|
|
return E_POINTER;
|
|
|
|
if ( IsEqualIID(riid, IID_IUnknown)
|
|
|| IsEqualIID(riid, IID_IPlaylistInfo))
|
|
{
|
|
*ppvObj = (IPlaylistInfo*) this;
|
|
}
|
|
else if (IsEqualIID(riid, IID_IDispatch))
|
|
{
|
|
*ppvObj = (IDispatch*) this;
|
|
}
|
|
else
|
|
{
|
|
*ppvObj = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
// *** IPlaylistInfo
|
|
//------------------------------------------------------------------------
|
|
//------------------------------------------------------------------------
|
|
STDMETHODIMP CPlaylistInfo::get_name(BSTR *pbstrName)
|
|
{
|
|
return _getStringProp(L"name", NULL, pbstrName);
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
STDMETHODIMP CPlaylistInfo::get_attributeCount(long *plCount)
|
|
{
|
|
if (plCount == NULL)
|
|
return E_POINTER;
|
|
*plCount = 0;
|
|
|
|
CComVariant vtValue;
|
|
HRESULT hr = _getVariantProp(L"attributeCount", NULL, &vtValue);
|
|
if (SUCCEEDED(hr) && (V_VT(&vtValue) == VT_I4))
|
|
{
|
|
*plCount = V_I4(&vtValue);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
STDMETHODIMP CPlaylistInfo::getAttributeName(long lIndex, BSTR *pbstrItemName)
|
|
{
|
|
CComVariant vtIndex = lIndex;
|
|
return _getStringProp(L"attributeName", &vtIndex, pbstrItemName);
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
STDMETHODIMP CPlaylistInfo::getItemInfo(BSTR bstrItemName, BSTR *pbstrVal)
|
|
{
|
|
CComVariant vtItemName = bstrItemName;
|
|
return _getStringProp(L"getItemInfo", &vtItemName, pbstrVal, TRUE);
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
HRESULT CPlaylistInfo::FetchWmpObject(IDispatch *pdispWmpPlayer, OUT VARIANT *pvtWrapperObj)
|
|
{
|
|
CComDispatchDriver pwmpPlayer;
|
|
pwmpPlayer = pdispWmpPlayer;
|
|
return pwmpPlayer.GetPropertyByName(L"currentPlaylist", pvtWrapperObj);
|
|
}
|
|
|
|
|