connectioncontainer.cpp
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:9k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * connectioncontainer.cpp: ActiveX control for VLC
  3.  *****************************************************************************
  4.  * Copyright (C) 2005 the VideoLAN team
  5.  *
  6.  * Authors: Damien Fouilleul <Damien.Fouilleul@laposte.net>
  7.  *
  8.  * This program is free software; you can redistribute it and/or modify
  9.  * it under the terms of the GNU General Public License as published by
  10.  * the Free Software Foundation; either version 2 of the License, or
  11.  * (at your option) any later version.
  12.  *
  13.  * This program is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  * GNU General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this program; if not, write to the Free Software
  20.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  21.  *****************************************************************************/
  22. #include "plugin.h"
  23. #include "connectioncontainer.h"
  24. #include "utils.h"
  25. using namespace std;
  26. ////////////////////////////////////////////////////////////////////////////////////////////////
  27. /* this function object is used to return the value from a map pair */
  28. struct VLCEnumConnectionsDereference
  29. {
  30.     CONNECTDATA operator()(const map<DWORD,LPUNKNOWN>::iterator& i)
  31.     {
  32.         CONNECTDATA cd;
  33.         i->second->AddRef();
  34.         cd.dwCookie = i->first;
  35.         cd.pUnk     = i->second;
  36.         return cd;
  37.     };
  38. };
  39. class VLCEnumConnections : public VLCEnumIterator<IID_IEnumConnections,
  40.     IEnumConnections,
  41.     CONNECTDATA,
  42.     map<DWORD,LPUNKNOWN>::iterator,
  43.     VLCEnumConnectionsDereference>
  44. {
  45. public:
  46.     VLCEnumConnections(map<DWORD,LPUNKNOWN> &m) :
  47.         VLCEnumIterator<IID_IEnumConnections,
  48.             IEnumConnections,
  49.             CONNECTDATA,
  50.             map<DWORD,LPUNKNOWN>::iterator,
  51.             VLCEnumConnectionsDereference> (m.begin(), m.end())
  52.     {};
  53. };
  54. ////////////////////////////////////////////////////////////////////////////////////////////////
  55. /* this function object is used to retain the dereferenced iterator value */
  56. struct VLCEnumConnectionPointsDereference
  57. {
  58.     LPCONNECTIONPOINT operator()(const vector<LPCONNECTIONPOINT>::iterator& i)
  59.     {
  60.         LPCONNECTIONPOINT cp = *i;
  61.         cp->AddRef();
  62.         return cp;
  63.     }
  64. };
  65. class VLCEnumConnectionPoints: public VLCEnumIterator<IID_IEnumConnectionPoints,
  66.     IEnumConnectionPoints,
  67.     LPCONNECTIONPOINT,
  68.     vector<LPCONNECTIONPOINT>::iterator,
  69.     VLCEnumConnectionPointsDereference>
  70. {
  71. public:
  72.     VLCEnumConnectionPoints(vector<LPCONNECTIONPOINT>& v) :
  73.         VLCEnumIterator<IID_IEnumConnectionPoints,
  74.             IEnumConnectionPoints,
  75.             LPCONNECTIONPOINT,
  76.             vector<LPCONNECTIONPOINT>::iterator,
  77.             VLCEnumConnectionPointsDereference> (v.begin(), v.end())
  78.     {};
  79. };
  80. ////////////////////////////////////////////////////////////////////////////////////////////////
  81. STDMETHODIMP VLCConnectionPoint::GetConnectionInterface(IID *iid)
  82. {
  83.     if( NULL == iid )
  84.         return E_POINTER;
  85.     *iid = _iid;
  86.     return S_OK;
  87. };
  88. STDMETHODIMP VLCConnectionPoint::GetConnectionPointContainer(LPCONNECTIONPOINTCONTAINER *ppCPC)
  89. {
  90.     if( NULL == ppCPC )
  91.         return E_POINTER;
  92.     _p_cpc->AddRef();
  93.     *ppCPC = _p_cpc;
  94.     return S_OK;
  95. };
  96. STDMETHODIMP VLCConnectionPoint::Advise(IUnknown *pUnk, DWORD *pdwCookie)
  97. {
  98.     static DWORD dwCookieCounter = 0;
  99.     if( (NULL == pUnk) || (NULL == pdwCookie) )
  100.         return E_POINTER;
  101.     if( SUCCEEDED(pUnk->QueryInterface(_iid, (LPVOID *)&pUnk)) )
  102.     {
  103.         *pdwCookie = ++dwCookieCounter;
  104.         _connections[*pdwCookie] = pUnk;
  105.         return S_OK;
  106.     }
  107.     return CONNECT_E_CANNOTCONNECT;
  108. };
  109. STDMETHODIMP VLCConnectionPoint::Unadvise(DWORD pdwCookie)
  110. {
  111.     map<DWORD,LPUNKNOWN>::iterator pcd = _connections.find((DWORD)pdwCookie);
  112.     if( pcd != _connections.end() )
  113.     {
  114.         pcd->second->Release();
  115.         _connections.erase(pdwCookie);
  116.         return S_OK;
  117.     }
  118.     return CONNECT_E_NOCONNECTION;
  119. };
  120. STDMETHODIMP VLCConnectionPoint::EnumConnections(IEnumConnections **ppEnum)
  121. {
  122.     if( NULL == ppEnum )
  123.         return E_POINTER;
  124.     *ppEnum = dynamic_cast<LPENUMCONNECTIONS>(new VLCEnumConnections(_connections));
  125.     return (NULL != *ppEnum ) ? S_OK : E_OUTOFMEMORY;
  126. };
  127. void VLCConnectionPoint::fireEvent(DISPID dispId, DISPPARAMS *pDispParams)
  128. {
  129.     map<DWORD,LPUNKNOWN>::iterator end = _connections.end();
  130.     map<DWORD,LPUNKNOWN>::iterator iter = _connections.begin();
  131.     while( iter != end )
  132.     {
  133.         LPUNKNOWN pUnk = iter->second;
  134.         if( NULL != pUnk )
  135.         {
  136.             IDispatch *pDisp;
  137.             if( SUCCEEDED(pUnk->QueryInterface(_iid, (LPVOID *)&pDisp)) )
  138.             {
  139.                 pDisp->Invoke(dispId, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, pDispParams, NULL, NULL, NULL);
  140.                 pDisp->Release();
  141.             }
  142.         }
  143.         ++iter;
  144.     }
  145. };
  146. void VLCConnectionPoint::firePropChangedEvent(DISPID dispId)
  147. {
  148.     map<DWORD,LPUNKNOWN>::iterator end = _connections.end();
  149.     map<DWORD,LPUNKNOWN>::iterator iter = _connections.begin();
  150.     while( iter != end )
  151.     {
  152.         LPUNKNOWN pUnk = iter->second;
  153.         if( NULL != pUnk )
  154.         {
  155.             IPropertyNotifySink *pPropSink;
  156.             if( SUCCEEDED(pUnk->QueryInterface(IID_IPropertyNotifySink, (LPVOID *)&pPropSink)) )
  157.             {
  158.                 pPropSink->OnChanged(dispId);
  159.                 pPropSink->Release();
  160.             }
  161.         }
  162.         ++iter;
  163.     }
  164. };
  165. ////////////////////////////////////////////////////////////////////////////////////////////////
  166. VLCDispatchEvent::~VLCDispatchEvent()
  167. {
  168.     //clear event arguments
  169.     if( NULL != _dispParams.rgvarg )
  170.     {
  171.         for(unsigned int c=0; c<_dispParams.cArgs; ++c)
  172.             VariantClear(_dispParams.rgvarg+c);
  173.         CoTaskMemFree(_dispParams.rgvarg);
  174.     }
  175.     if( NULL != _dispParams.rgdispidNamedArgs )
  176.         CoTaskMemFree(_dispParams.rgdispidNamedArgs);
  177. };
  178. ////////////////////////////////////////////////////////////////////////////////////////////////
  179. VLCConnectionPointContainer::VLCConnectionPointContainer(VLCPlugin *p_instance) :
  180.     _p_instance(p_instance), _b_freeze(FALSE)
  181. {
  182.     _p_events = new VLCConnectionPoint(dynamic_cast<LPCONNECTIONPOINTCONTAINER>(this),
  183.             _p_instance->getDispEventID());
  184.     _v_cps.push_back(dynamic_cast<LPCONNECTIONPOINT>(_p_events));
  185.     _p_props = new VLCConnectionPoint(dynamic_cast<LPCONNECTIONPOINTCONTAINER>(this),
  186.             IID_IPropertyNotifySink);
  187.     _v_cps.push_back(dynamic_cast<LPCONNECTIONPOINT>(_p_props));
  188. };
  189. VLCConnectionPointContainer::~VLCConnectionPointContainer()
  190. {
  191.     delete _p_props;
  192.     delete _p_events;
  193. };
  194. STDMETHODIMP VLCConnectionPointContainer::EnumConnectionPoints(LPENUMCONNECTIONPOINTS *ppEnum)
  195. {
  196.     if( NULL == ppEnum )
  197.         return E_POINTER;
  198.     *ppEnum = dynamic_cast<LPENUMCONNECTIONPOINTS>(new VLCEnumConnectionPoints(_v_cps));
  199.     return (NULL != *ppEnum ) ? S_OK : E_OUTOFMEMORY;
  200. };
  201. STDMETHODIMP VLCConnectionPointContainer::FindConnectionPoint(REFIID riid, IConnectionPoint **ppCP)
  202. {
  203.     if( NULL == ppCP )
  204.         return E_POINTER;
  205.     *ppCP = NULL;
  206.     if( IID_IPropertyNotifySink == riid )
  207.     {
  208.         _p_props->AddRef();
  209.         *ppCP = dynamic_cast<LPCONNECTIONPOINT>(_p_props);
  210.     }
  211.     else if( _p_instance->getDispEventID() == riid )
  212.     {
  213.         _p_events->AddRef();
  214.         *ppCP = dynamic_cast<LPCONNECTIONPOINT>(_p_events);
  215.     }
  216.     else
  217.         return CONNECT_E_NOCONNECTION;
  218.     return NOERROR;
  219. };
  220. void VLCConnectionPointContainer::freezeEvents(BOOL freeze)
  221. {
  222.     if( ! freeze )
  223.     {
  224.         // release queued events
  225.         while( ! _q_events.empty() )
  226.         {
  227.             VLCDispatchEvent *ev = _q_events.front();
  228.             _q_events.pop();
  229.             _p_events->fireEvent(ev->_dispId, &ev->_dispParams);
  230.             delete ev;
  231.         }
  232.     }
  233.     _b_freeze = freeze;
  234. };
  235. void VLCConnectionPointContainer::fireEvent(DISPID dispId, DISPPARAMS* pDispParams)
  236. {
  237.     if( _b_freeze )
  238.     {
  239.         // queue event for later use when container is ready
  240.         _q_events.push(new VLCDispatchEvent(dispId, *pDispParams));
  241.         if( _q_events.size() > 10 )
  242.         {
  243.             // too many events in queue, get rid of older one
  244.             delete _q_events.front();
  245.             _q_events.pop();
  246.         }
  247.     }
  248.     else
  249.     {
  250.         _p_events->fireEvent(dispId, pDispParams);
  251.     }
  252. };
  253. void VLCConnectionPointContainer::firePropChangedEvent(DISPID dispId)
  254. {
  255.     if( ! _b_freeze )
  256.         _p_props->firePropChangedEvent(dispId);
  257. };