00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
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
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
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
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
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
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
00313 _q_events.push(new VLCDispatchEvent(dispId, *pDispParams));
00314 if( _q_events.size() > 10 )
00315 {
00316
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