X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=activex%2Fconnectioncontainer.cpp;h=757f5139154175b1e8f0a5f08479c3060c248bb8;hb=61630d2bd57b7e621263e4a1b7f61f7987caacc6;hp=6fd504a6980bc8ab5af4af94cc737233bfd6c794;hpb=f533f3d8aa01c57102e16a829fe9146b35a32cef;p=vlc diff --git a/activex/connectioncontainer.cpp b/activex/connectioncontainer.cpp index 6fd504a698..757f513915 100644 --- a/activex/connectioncontainer.cpp +++ b/activex/connectioncontainer.cpp @@ -1,287 +1,304 @@ -/***************************************************************************** - * connectioncontainer.cpp: ActiveX control for VLC - ***************************************************************************** - * Copyright (C) 2005 VideoLAN - * - * Authors: Damien Fouilleul - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. - *****************************************************************************/ - -#include "plugin.h" -#include "connectioncontainer.h" - -#include "utils.h" - -using namespace std; - -//////////////////////////////////////////////////////////////////////////////////////////////// - -class VLCEnumConnections : public IEnumConnections -{ -public: - VLCEnumConnections(vector &v) : - e(VLCEnum(IID_IEnumConnections, v)) - { e.setRetainOperation((VLCEnum::retainer)&retain); }; - - VLCEnumConnections(const VLCEnumConnections &vlcEnum) : e(vlcEnum.e) {}; - - virtual ~VLCEnumConnections() {}; - - // IUnknown methods - STDMETHODIMP QueryInterface(REFIID riid, void **ppv) - { return e.QueryInterface(riid, ppv); }; - STDMETHODIMP_(ULONG) AddRef(void) - { return e.AddRef(); }; - STDMETHODIMP_(ULONG) Release(void) - {return e.Release(); }; - - //IEnumConnectionPoints - STDMETHODIMP Next(ULONG celt, LPCONNECTDATA rgelt, ULONG *pceltFetched) - { return e.Next(celt, rgelt, pceltFetched); }; - STDMETHODIMP Skip(ULONG celt) - { return e.Skip(celt);}; - STDMETHODIMP Reset(void) - { return e.Reset();}; - STDMETHODIMP Clone(LPENUMCONNECTIONS *ppenum) - { if( NULL == ppenum ) return E_POINTER; - *ppenum = dynamic_cast(new VLCEnumConnections(*this)); - return (NULL != *ppenum) ? S_OK : E_OUTOFMEMORY; - }; - -private: - - static void retain(CONNECTDATA cd) - { - cd.pUnk->AddRef(); - }; - - VLCEnum e; -}; - -//////////////////////////////////////////////////////////////////////////////////////////////// - -STDMETHODIMP VLCConnectionPoint::GetConnectionInterface(IID *iid) -{ - if( NULL == iid ) - return E_POINTER; - - *iid = _iid; - return S_OK; -}; - -STDMETHODIMP VLCConnectionPoint::GetConnectionPointContainer(LPCONNECTIONPOINTCONTAINER *ppCPC) -{ - if( NULL == ppCPC ) - return E_POINTER; - - _p_cpc->AddRef(); - *ppCPC = _p_cpc; - return S_OK; -}; - -STDMETHODIMP VLCConnectionPoint::Advise(IUnknown *pUnk, DWORD *pdwCookie) -{ - if( (NULL == pUnk) || (NULL == pdwCookie) ) - return E_POINTER; - - CONNECTDATA cd; - - pUnk->AddRef(); - cd.pUnk = pUnk; - *pdwCookie = cd.dwCookie = _connections.size(); - - _connections.push_back(cd); - - return S_OK; -}; - -STDMETHODIMP VLCConnectionPoint::Unadvise(DWORD pdwCookie) -{ - if( pdwCookie < _connections.size() ) - { - CONNECTDATA cd = _connections[pdwCookie]; - if( NULL != cd.pUnk ) - { - cd.pUnk->Release(); - cd.pUnk = NULL; - return S_OK; - } - } - return CONNECT_E_NOCONNECTION; -}; - -STDMETHODIMP VLCConnectionPoint::EnumConnections(IEnumConnections **ppEnum) -{ - if( NULL == ppEnum ) - return E_POINTER; - - *ppEnum = dynamic_cast(new VLCEnumConnections(_connections)); - - return (NULL != *ppEnum ) ? S_OK : E_OUTOFMEMORY; -}; - -void VLCConnectionPoint::fireEvent(DISPID dispId, DISPPARAMS* pDispParams) -{ - vector::iterator end = _connections.end(); - vector::iterator iter = _connections.begin(); - - while( iter != end ) - { - CONNECTDATA cd = *iter; - if( NULL != cd.pUnk ) - { - IDispatch *pDisp; - if( SUCCEEDED(cd.pUnk->QueryInterface(IID_IDispatch, (LPVOID *)&pDisp)) ) - { - pDisp->Invoke(dispId, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, pDispParams, NULL, NULL, NULL); - pDisp->Release(); - } - } - ++iter; - } -}; - -void VLCConnectionPoint::firePropChangedEvent(DISPID dispId) -{ - vector::iterator end = _connections.end(); - vector::iterator iter = _connections.begin(); - - while( iter != end ) - { - CONNECTDATA cd = *iter; - if( NULL != cd.pUnk ) - { - IPropertyNotifySink *pPropSink; - if( SUCCEEDED(cd.pUnk->QueryInterface(IID_IPropertyNotifySink, (LPVOID *)&pPropSink)) ) - { - pPropSink->OnChanged(dispId); - pPropSink->Release(); - } - } - ++iter; - } -}; - -//////////////////////////////////////////////////////////////////////////////////////////////// - -class VLCEnumConnectionPoints : public IEnumConnectionPoints -{ -public: - VLCEnumConnectionPoints(vector &v) : - e(VLCEnum(IID_IEnumConnectionPoints, v)) - { e.setRetainOperation((VLCEnum::retainer)&retain); }; - - VLCEnumConnectionPoints(const VLCEnumConnectionPoints &vlcEnum) : e(vlcEnum.e) {}; - - virtual ~VLCEnumConnectionPoints() {}; - - // IUnknown methods - STDMETHODIMP QueryInterface(REFIID riid, void **ppv) - { return e.QueryInterface(riid, ppv); }; - STDMETHODIMP_(ULONG) AddRef(void) - { return e.AddRef(); }; - STDMETHODIMP_(ULONG) Release(void) - {return e.Release(); }; - - //IEnumConnectionPoints - STDMETHODIMP Next(ULONG celt, LPCONNECTIONPOINT *rgelt, ULONG *pceltFetched) - { return e.Next(celt, rgelt, pceltFetched); }; - STDMETHODIMP Skip(ULONG celt) - { return e.Skip(celt);}; - STDMETHODIMP Reset(void) - { return e.Reset();}; - STDMETHODIMP Clone(LPENUMCONNECTIONPOINTS *ppenum) - { if( NULL == ppenum ) return E_POINTER; - *ppenum = dynamic_cast(new VLCEnumConnectionPoints(*this)); - return (NULL != *ppenum) ? S_OK : E_OUTOFMEMORY; - }; - -private: - - static void retain(LPCONNECTIONPOINT cp) - { - cp->AddRef(); - }; - - VLCEnum e; -}; - -//////////////////////////////////////////////////////////////////////////////////////////////// - -VLCConnectionPointContainer::VLCConnectionPointContainer(VLCPlugin *p_instance) : - _p_instance(p_instance) -{ - _p_events = new VLCConnectionPoint(dynamic_cast(this), - _p_instance->getDispEventID()); - - _v_cps.push_back(dynamic_cast(_p_events)); - - _p_props = new VLCConnectionPoint(dynamic_cast(this), - IID_IPropertyNotifySink); - - _v_cps.push_back(dynamic_cast(_p_props)); -}; - -VLCConnectionPointContainer::~VLCConnectionPointContainer() -{ - _v_cps.clear(); - delete _p_props; - delete _p_events; -}; - -STDMETHODIMP VLCConnectionPointContainer::EnumConnectionPoints(LPENUMCONNECTIONPOINTS *ppEnum) -{ - if( NULL == ppEnum ) - return E_POINTER; - - *ppEnum = dynamic_cast(new VLCEnumConnectionPoints(_v_cps)); - - return (NULL != *ppEnum ) ? S_OK : E_OUTOFMEMORY; -}; - -STDMETHODIMP VLCConnectionPointContainer::FindConnectionPoint(REFIID riid, IConnectionPoint **ppCP) -{ - if( NULL == ppCP ) - return E_POINTER; - - *ppCP = NULL; - - if( IID_IPropertyNotifySink == riid ) - { - _p_props->AddRef(); - *ppCP = dynamic_cast(_p_props); - } - else if( _p_instance->getDispEventID() == riid ) - { - _p_events->AddRef(); - *ppCP = dynamic_cast(_p_events); - } - else - return CONNECT_E_NOCONNECTION; - - return NOERROR; -}; - -void VLCConnectionPointContainer::fireEvent(DISPID dispId, DISPPARAMS* pDispParams) -{ - _p_events->fireEvent(dispId, pDispParams); -}; - -void VLCConnectionPointContainer::firePropChangedEvent(DISPID dispId) -{ - _p_props->firePropChangedEvent(dispId); -}; - +/***************************************************************************** + * connectioncontainer.cpp: ActiveX control for VLC + ***************************************************************************** + * Copyright (C) 2005 the VideoLAN team + * + * Authors: Damien Fouilleul + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +#include "plugin.h" +#include "connectioncontainer.h" + +#include "utils.h" + +using namespace std; + +//////////////////////////////////////////////////////////////////////////////////////////////// + +/* this function object is used to return the value from a map pair */ +struct VLCEnumConnectionsDereference +{ + CONNECTDATA operator()(const map::iterator& i) + { + CONNECTDATA cd; + + i->second->AddRef(); + + cd.dwCookie = i->first; + cd.pUnk = i->second; + return cd; + }; +}; + +class VLCEnumConnections : public VLCEnumIterator::iterator, + VLCEnumConnectionsDereference> +{ +public: + VLCEnumConnections(map &m) : + VLCEnumIterator::iterator, + VLCEnumConnectionsDereference> (m.begin(), m.end()) + {}; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////// + +/* this function object is used to retain the dereferenced iterator value */ +struct VLCEnumConnectionPointsDereference +{ + LPCONNECTIONPOINT operator()(const vector::iterator& i) + { + LPCONNECTIONPOINT cp = *i; + cp->AddRef(); + return cp; + } +}; + +class VLCEnumConnectionPoints: public VLCEnumIterator::iterator, + VLCEnumConnectionPointsDereference> +{ +public: + VLCEnumConnectionPoints(vector& v) : + VLCEnumIterator::iterator, + VLCEnumConnectionPointsDereference> (v.begin(), v.end()) + {}; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////// + +STDMETHODIMP VLCConnectionPoint::GetConnectionInterface(IID *iid) +{ + if( NULL == iid ) + return E_POINTER; + + *iid = _iid; + return S_OK; +}; + +STDMETHODIMP VLCConnectionPoint::GetConnectionPointContainer(LPCONNECTIONPOINTCONTAINER *ppCPC) +{ + if( NULL == ppCPC ) + return E_POINTER; + + _p_cpc->AddRef(); + *ppCPC = _p_cpc; + return S_OK; +}; + +STDMETHODIMP VLCConnectionPoint::Advise(IUnknown *pUnk, DWORD *pdwCookie) +{ + static DWORD dwCookieCounter = 0; + + if( (NULL == pUnk) || (NULL == pdwCookie) ) + return E_POINTER; + + if( SUCCEEDED(pUnk->QueryInterface(_iid, (LPVOID *)&pUnk)) ) + { + *pdwCookie = ++dwCookieCounter; + _connections[*pdwCookie] = pUnk; + return S_OK; + } + return CONNECT_E_CANNOTCONNECT; +}; + +STDMETHODIMP VLCConnectionPoint::Unadvise(DWORD pdwCookie) +{ + map::iterator pcd = _connections.find((DWORD)pdwCookie); + if( pcd != _connections.end() ) + { + pcd->second->Release(); + + _connections.erase(pdwCookie); + return S_OK; + } + return CONNECT_E_NOCONNECTION; +}; + +STDMETHODIMP VLCConnectionPoint::EnumConnections(IEnumConnections **ppEnum) +{ + if( NULL == ppEnum ) + return E_POINTER; + + *ppEnum = dynamic_cast(new VLCEnumConnections(_connections)); + + return (NULL != *ppEnum ) ? S_OK : E_OUTOFMEMORY; +}; + +void VLCConnectionPoint::fireEvent(DISPID dispId, DISPPARAMS *pDispParams) +{ + map::iterator end = _connections.end(); + map::iterator iter = _connections.begin(); + + while( iter != end ) + { + LPUNKNOWN pUnk = iter->second; + if( NULL != pUnk ) + { + IDispatch *pDisp; + if( SUCCEEDED(pUnk->QueryInterface(_iid, (LPVOID *)&pDisp)) ) + { + pDisp->Invoke(dispId, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, pDispParams, NULL, NULL, NULL); + pDisp->Release(); + } + } + ++iter; + } +}; + +void VLCConnectionPoint::firePropChangedEvent(DISPID dispId) +{ + map::iterator end = _connections.end(); + map::iterator iter = _connections.begin(); + + while( iter != end ) + { + LPUNKNOWN pUnk = iter->second; + if( NULL != pUnk ) + { + IPropertyNotifySink *pPropSink; + if( SUCCEEDED(pUnk->QueryInterface(IID_IPropertyNotifySink, (LPVOID *)&pPropSink)) ) + { + pPropSink->OnChanged(dispId); + pPropSink->Release(); + } + } + ++iter; + } +}; + +//////////////////////////////////////////////////////////////////////////////////////////////// + +VLCDispatchEvent::~VLCDispatchEvent() +{ + //clear event arguments + if( NULL != _dispParams.rgvarg ) + { + for(unsigned int c=0; c<_dispParams.cArgs; ++c) + VariantClear(_dispParams.rgvarg+c); + CoTaskMemFree(_dispParams.rgvarg); + } + if( NULL != _dispParams.rgdispidNamedArgs ) + CoTaskMemFree(_dispParams.rgdispidNamedArgs); +}; + +//////////////////////////////////////////////////////////////////////////////////////////////// + +VLCConnectionPointContainer::VLCConnectionPointContainer(VLCPlugin *p_instance) : + _p_instance(p_instance), _b_freeze(FALSE) +{ + _p_events = new VLCConnectionPoint(dynamic_cast(this), + _p_instance->getDispEventID()); + + _v_cps.push_back(dynamic_cast(_p_events)); + + _p_props = new VLCConnectionPoint(dynamic_cast(this), + IID_IPropertyNotifySink); + + _v_cps.push_back(dynamic_cast(_p_props)); +}; + +VLCConnectionPointContainer::~VLCConnectionPointContainer() +{ + delete _p_props; + delete _p_events; +}; + +STDMETHODIMP VLCConnectionPointContainer::EnumConnectionPoints(LPENUMCONNECTIONPOINTS *ppEnum) +{ + if( NULL == ppEnum ) + return E_POINTER; + + *ppEnum = dynamic_cast(new VLCEnumConnectionPoints(_v_cps)); + + return (NULL != *ppEnum ) ? S_OK : E_OUTOFMEMORY; +}; + +STDMETHODIMP VLCConnectionPointContainer::FindConnectionPoint(REFIID riid, IConnectionPoint **ppCP) +{ + if( NULL == ppCP ) + return E_POINTER; + + *ppCP = NULL; + + if( IID_IPropertyNotifySink == riid ) + { + _p_props->AddRef(); + *ppCP = dynamic_cast(_p_props); + } + else if( _p_instance->getDispEventID() == riid ) + { + _p_events->AddRef(); + *ppCP = dynamic_cast(_p_events); + } + else + return CONNECT_E_NOCONNECTION; + + return NOERROR; +}; + +void VLCConnectionPointContainer::freezeEvents(BOOL freeze) +{ + if( ! freeze ) + { + // release queued events + while( ! _q_events.empty() ) + { + VLCDispatchEvent *ev = _q_events.front(); + _q_events.pop(); + _p_events->fireEvent(ev->_dispId, &ev->_dispParams); + delete ev; + } + } + _b_freeze = freeze; +}; + +void VLCConnectionPointContainer::fireEvent(DISPID dispId, DISPPARAMS* pDispParams) +{ + if( _b_freeze ) + { + // queue event for later use when container is ready + _q_events.push(new VLCDispatchEvent(dispId, *pDispParams)); + if( _q_events.size() > 10 ) + { + // too many events in queue, get rid of older one + delete _q_events.front(); + _q_events.pop(); + } + } + else + { + _p_events->fireEvent(dispId, pDispParams); + } +}; + +void VLCConnectionPointContainer::firePropChangedEvent(DISPID dispId) +{ + if( ! _b_freeze ) + _p_props->firePropChangedEvent(dispId); +}; +