Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

connectioncontainer.cpp

00001 /*****************************************************************************
00002  * connectioncontainer.cpp: ActiveX control for VLC
00003  *****************************************************************************
00004  * Copyright (C) 2005 the VideoLAN team
00005  *
00006  * Authors: Damien Fouilleul <[email protected]>
00007  *
00008  * This program is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00021  *****************************************************************************/
00022 
00023 #include "plugin.h"
00024 #include "connectioncontainer.h"
00025 
00026 #include "utils.h"
00027 
00028 using namespace std;
00029 
00031 
00032 class VLCEnumConnections : public IEnumConnections
00033 {
00034 public:
00035     VLCEnumConnections(vector<CONNECTDATA> &v) :
00036         e(VLCEnum<CONNECTDATA>(IID_IEnumConnections, v))
00037     { e.setRetainOperation((VLCEnum<CONNECTDATA>::retainer)&retain); };
00038 
00039     VLCEnumConnections(const VLCEnumConnections &vlcEnum) : e(vlcEnum.e) {};
00040 
00041     virtual ~VLCEnumConnections() {};
00042 
00043     // IUnknown methods
00044     STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
00045         { return e.QueryInterface(riid, ppv); };
00046     STDMETHODIMP_(ULONG) AddRef(void)
00047         { return e.AddRef(); };
00048     STDMETHODIMP_(ULONG) Release(void)
00049         {return e.Release(); };
00050 
00051     //IEnumConnectionPoints
00052     STDMETHODIMP Next(ULONG celt, LPCONNECTDATA rgelt, ULONG *pceltFetched)
00053         { return e.Next(celt, rgelt, pceltFetched); };
00054     STDMETHODIMP Skip(ULONG celt)
00055         { return e.Skip(celt);};
00056     STDMETHODIMP Reset(void)
00057         { return e.Reset();};
00058     STDMETHODIMP Clone(LPENUMCONNECTIONS *ppenum)
00059         { if( NULL == ppenum ) return E_POINTER;
00060           *ppenum = dynamic_cast<LPENUMCONNECTIONS>(new VLCEnumConnections(*this));
00061           return (NULL != *ppenum) ? S_OK : E_OUTOFMEMORY;
00062         };
00063 
00064 private:
00065 
00066     static void retain(CONNECTDATA cd)
00067     {
00068         cd.pUnk->AddRef();
00069     };
00070 
00071     VLCEnum<CONNECTDATA> e;
00072 };
00073 
00075 
00076 STDMETHODIMP VLCConnectionPoint::GetConnectionInterface(IID *iid)
00077 {
00078     if( NULL == iid )
00079         return E_POINTER;
00080 
00081     *iid = _iid;
00082     return S_OK;
00083 };
00084 
00085 STDMETHODIMP VLCConnectionPoint::GetConnectionPointContainer(LPCONNECTIONPOINTCONTAINER *ppCPC)
00086 {
00087     if( NULL == ppCPC )
00088         return E_POINTER;
00089 
00090     _p_cpc->AddRef();
00091     *ppCPC = _p_cpc;
00092     return S_OK;
00093 };
00094 
00095 STDMETHODIMP VLCConnectionPoint::Advise(IUnknown *pUnk, DWORD *pdwCookie)
00096 {
00097     if( (NULL == pUnk) || (NULL == pdwCookie) )
00098         return E_POINTER;
00099 
00100     CONNECTDATA cd;
00101 
00102     pUnk->AddRef();
00103     cd.pUnk = pUnk;
00104     *pdwCookie = cd.dwCookie = _connections.size();
00105 
00106     _connections.push_back(cd);
00107 
00108     return S_OK;
00109 };
00110 
00111 STDMETHODIMP VLCConnectionPoint::Unadvise(DWORD pdwCookie)
00112 {
00113     if( pdwCookie < _connections.size() )
00114     {
00115         CONNECTDATA cd = _connections[pdwCookie];
00116         if( NULL != cd.pUnk )
00117         {
00118             cd.pUnk->Release();
00119             cd.pUnk = NULL;
00120             return S_OK;
00121         }
00122     }
00123     return CONNECT_E_NOCONNECTION;
00124 };
00125 
00126 STDMETHODIMP VLCConnectionPoint::EnumConnections(IEnumConnections **ppEnum)
00127 {
00128     if( NULL == ppEnum )
00129         return E_POINTER;
00130 
00131     *ppEnum = dynamic_cast<LPENUMCONNECTIONS>(new VLCEnumConnections(_connections));
00132 
00133     return (NULL != *ppEnum ) ? S_OK : E_OUTOFMEMORY;
00134 };
00135 
00136 void VLCConnectionPoint::fireEvent(DISPID dispId, DISPPARAMS *pDispParams)
00137 {
00138     vector<CONNECTDATA>::iterator end = _connections.end();
00139     vector<CONNECTDATA>::iterator iter = _connections.begin();
00140 
00141     while( iter != end )
00142     {
00143         CONNECTDATA cd = *iter;
00144         if( NULL != cd.pUnk )
00145         {
00146             IDispatch *pDisp;
00147             if( SUCCEEDED(cd.pUnk->QueryInterface(IID_IDispatch, (LPVOID *)&pDisp)) )
00148             {
00149                 pDisp->Invoke(dispId, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, pDispParams, NULL, NULL, NULL);
00150                 pDisp->Release();
00151             }
00152         }
00153         ++iter;
00154     }
00155 };
00156 
00157 void VLCConnectionPoint::firePropChangedEvent(DISPID dispId)
00158 {
00159     vector<CONNECTDATA>::iterator end = _connections.end();
00160     vector<CONNECTDATA>::iterator iter = _connections.begin();
00161 
00162     while( iter != end )
00163     {
00164         CONNECTDATA cd = *iter;
00165         if( NULL != cd.pUnk )
00166         {
00167             IPropertyNotifySink *pPropSink;
00168             if( SUCCEEDED(cd.pUnk->QueryInterface(IID_IPropertyNotifySink, (LPVOID *)&pPropSink)) )
00169             {
00170                 pPropSink->OnChanged(dispId);
00171                 pPropSink->Release();
00172             }
00173         }
00174         ++iter;
00175     }
00176 };
00177 
00179 
00180 class VLCEnumConnectionPoints : public IEnumConnectionPoints
00181 {
00182 public:
00183     VLCEnumConnectionPoints(vector<LPCONNECTIONPOINT> &v) :
00184         e(VLCEnum<LPCONNECTIONPOINT>(IID_IEnumConnectionPoints, v))
00185     { e.setRetainOperation((VLCEnum<LPCONNECTIONPOINT>::retainer)&retain); };
00186 
00187     VLCEnumConnectionPoints(const VLCEnumConnectionPoints &vlcEnum) : e(vlcEnum.e) {};
00188 
00189     virtual ~VLCEnumConnectionPoints() {};
00190 
00191     // IUnknown methods
00192     STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
00193         { return e.QueryInterface(riid, ppv); };
00194     STDMETHODIMP_(ULONG) AddRef(void)
00195         { return e.AddRef(); };
00196     STDMETHODIMP_(ULONG) Release(void)
00197         {return e.Release(); };
00198 
00199     //IEnumConnectionPoints
00200     STDMETHODIMP Next(ULONG celt, LPCONNECTIONPOINT *rgelt, ULONG *pceltFetched)
00201         { return e.Next(celt, rgelt, pceltFetched); };
00202     STDMETHODIMP Skip(ULONG celt)
00203         { return e.Skip(celt);};
00204     STDMETHODIMP Reset(void)
00205         { return e.Reset();};
00206     STDMETHODIMP Clone(LPENUMCONNECTIONPOINTS *ppenum)
00207         { if( NULL == ppenum ) return E_POINTER;
00208           *ppenum = dynamic_cast<LPENUMCONNECTIONPOINTS>(new VLCEnumConnectionPoints(*this));
00209           return (NULL != *ppenum) ? S_OK : E_OUTOFMEMORY;
00210         };
00211 
00212 private:
00213 
00214     static void retain(LPCONNECTIONPOINT cp)
00215     {
00216         cp->AddRef();
00217     };
00218 
00219     VLCEnum<LPCONNECTIONPOINT> e;
00220 };
00221 
00223 
00224 VLCDispatchEvent::~VLCDispatchEvent()
00225 {
00226     //clear event arguments
00227     if( NULL != _dispParams.rgvarg )
00228     {
00229         for(unsigned int c=0; c<_dispParams.cArgs; ++c)
00230             VariantClear(_dispParams.rgvarg+c);
00231         CoTaskMemFree(_dispParams.rgvarg);
00232     }
00233     if( NULL != _dispParams.rgdispidNamedArgs )
00234         CoTaskMemFree(_dispParams.rgdispidNamedArgs);
00235 };
00236 
00238 
00239 VLCConnectionPointContainer::VLCConnectionPointContainer(VLCPlugin *p_instance) :
00240     _p_instance(p_instance), _b_freeze(FALSE)
00241 {
00242     _p_events = new VLCConnectionPoint(dynamic_cast<LPCONNECTIONPOINTCONTAINER>(this),
00243             _p_instance->getDispEventID());
00244 
00245     _v_cps.push_back(dynamic_cast<LPCONNECTIONPOINT>(_p_events));
00246 
00247     _p_props = new VLCConnectionPoint(dynamic_cast<LPCONNECTIONPOINTCONTAINER>(this),
00248             IID_IPropertyNotifySink);
00249 
00250     _v_cps.push_back(dynamic_cast<LPCONNECTIONPOINT>(_p_props));
00251 };
00252 
00253 VLCConnectionPointContainer::~VLCConnectionPointContainer()
00254 {
00255     delete _p_props;
00256     delete _p_events;
00257 };
00258 
00259 STDMETHODIMP VLCConnectionPointContainer::EnumConnectionPoints(LPENUMCONNECTIONPOINTS *ppEnum)
00260 {
00261     if( NULL == ppEnum )
00262         return E_POINTER;
00263 
00264     *ppEnum = dynamic_cast<LPENUMCONNECTIONPOINTS>(new VLCEnumConnectionPoints(_v_cps));
00265 
00266     return (NULL != *ppEnum ) ? S_OK : E_OUTOFMEMORY;
00267 };
00268 
00269 STDMETHODIMP VLCConnectionPointContainer::FindConnectionPoint(REFIID riid, IConnectionPoint **ppCP)
00270 {
00271     if( NULL == ppCP )
00272         return E_POINTER;
00273 
00274     *ppCP = NULL;
00275 
00276     if( IID_IPropertyNotifySink == riid )
00277     {
00278         _p_props->AddRef();
00279         *ppCP = dynamic_cast<LPCONNECTIONPOINT>(_p_props);
00280     }
00281     else if( _p_instance->getDispEventID() == riid )
00282     {
00283         _p_events->AddRef();
00284         *ppCP = dynamic_cast<LPCONNECTIONPOINT>(_p_events);
00285     }
00286     else
00287         return CONNECT_E_NOCONNECTION;
00288 
00289     return NOERROR;
00290 };
00291 
00292 void VLCConnectionPointContainer::freezeEvents(BOOL freeze)
00293 {
00294     if( ! freeze )
00295     {
00296         // release queued events
00297         while( ! _q_events.empty() )
00298         {
00299             VLCDispatchEvent *ev = _q_events.front();
00300             _q_events.pop();
00301             _p_events->fireEvent(ev->_dispId, &ev->_dispParams);
00302             delete ev;
00303         }
00304     }
00305     _b_freeze = freeze;
00306 };
00307 
00308 void VLCConnectionPointContainer::fireEvent(DISPID dispId, DISPPARAMS* pDispParams)
00309 {
00310     if( _b_freeze )
00311     {
00312         // queue event for later use when container is ready
00313         _q_events.push(new VLCDispatchEvent(dispId, *pDispParams));
00314         if( _q_events.size() > 10 )
00315         {
00316             // too many events in queue, get rid of older one
00317             delete _q_events.front();
00318             _q_events.pop();
00319         }
00320     }
00321     else
00322     {
00323         _p_events->fireEvent(dispId, pDispParams);
00324     }
00325 };
00326 
00327 void VLCConnectionPointContainer::firePropChangedEvent(DISPID dispId)
00328 {
00329     if( ! _b_freeze )
00330         _p_props->firePropChangedEvent(dispId);
00331 };
00332 

Generated on Tue Dec 20 10:14:18 2005 for vlc-0.8.4a by  doxygen 1.4.2