1 /*****************************************************************************
2 * connectioncontainer.cpp: ActiveX control for VLC
3 *****************************************************************************
4 * Copyright (C) 2005 the VideoLAN team
6 * Authors: Damien Fouilleul <Damien.Fouilleul@laposte.net>
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.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
21 *****************************************************************************/
24 #include "connectioncontainer.h"
30 ////////////////////////////////////////////////////////////////////////////////////////////////
32 class VLCEnumConnections : public IEnumConnections
35 VLCEnumConnections(vector<CONNECTDATA> &v) :
36 e(VLCEnum<CONNECTDATA>(IID_IEnumConnections, v))
37 { e.setRetainOperation((VLCEnum<CONNECTDATA>::retainer)&retain); };
39 VLCEnumConnections(const VLCEnumConnections &vlcEnum) : e(vlcEnum.e) {};
41 virtual ~VLCEnumConnections() {};
44 STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
45 { return e.QueryInterface(riid, ppv); };
46 STDMETHODIMP_(ULONG) AddRef(void)
47 { return e.AddRef(); };
48 STDMETHODIMP_(ULONG) Release(void)
49 {return e.Release(); };
51 //IEnumConnectionPoints
52 STDMETHODIMP Next(ULONG celt, LPCONNECTDATA rgelt, ULONG *pceltFetched)
53 { return e.Next(celt, rgelt, pceltFetched); };
54 STDMETHODIMP Skip(ULONG celt)
55 { return e.Skip(celt);};
56 STDMETHODIMP Reset(void)
58 STDMETHODIMP Clone(LPENUMCONNECTIONS *ppenum)
59 { if( NULL == ppenum ) return E_POINTER;
60 *ppenum = dynamic_cast<LPENUMCONNECTIONS>(new VLCEnumConnections(*this));
61 return (NULL != *ppenum) ? S_OK : E_OUTOFMEMORY;
66 static void retain(CONNECTDATA cd)
71 VLCEnum<CONNECTDATA> e;
74 ////////////////////////////////////////////////////////////////////////////////////////////////
76 STDMETHODIMP VLCConnectionPoint::GetConnectionInterface(IID *iid)
85 STDMETHODIMP VLCConnectionPoint::GetConnectionPointContainer(LPCONNECTIONPOINTCONTAINER *ppCPC)
95 STDMETHODIMP VLCConnectionPoint::Advise(IUnknown *pUnk, DWORD *pdwCookie)
97 if( (NULL == pUnk) || (NULL == pdwCookie) )
104 *pdwCookie = cd.dwCookie = _connections.size();
106 _connections.push_back(cd);
111 STDMETHODIMP VLCConnectionPoint::Unadvise(DWORD pdwCookie)
113 if( pdwCookie < _connections.size() )
115 CONNECTDATA cd = _connections[pdwCookie];
116 if( NULL != cd.pUnk )
123 return CONNECT_E_NOCONNECTION;
126 STDMETHODIMP VLCConnectionPoint::EnumConnections(IEnumConnections **ppEnum)
131 *ppEnum = dynamic_cast<LPENUMCONNECTIONS>(new VLCEnumConnections(_connections));
133 return (NULL != *ppEnum ) ? S_OK : E_OUTOFMEMORY;
136 void VLCConnectionPoint::fireEvent(DISPID dispId, DISPPARAMS *pDispParams)
138 vector<CONNECTDATA>::iterator end = _connections.end();
139 vector<CONNECTDATA>::iterator iter = _connections.begin();
143 CONNECTDATA cd = *iter;
144 if( NULL != cd.pUnk )
147 if( SUCCEEDED(cd.pUnk->QueryInterface(IID_IDispatch, (LPVOID *)&pDisp)) )
149 pDisp->Invoke(dispId, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, pDispParams, NULL, NULL, NULL);
157 void VLCConnectionPoint::firePropChangedEvent(DISPID dispId)
159 vector<CONNECTDATA>::iterator end = _connections.end();
160 vector<CONNECTDATA>::iterator iter = _connections.begin();
164 CONNECTDATA cd = *iter;
165 if( NULL != cd.pUnk )
167 IPropertyNotifySink *pPropSink;
168 if( SUCCEEDED(cd.pUnk->QueryInterface(IID_IPropertyNotifySink, (LPVOID *)&pPropSink)) )
170 pPropSink->OnChanged(dispId);
171 pPropSink->Release();
178 ////////////////////////////////////////////////////////////////////////////////////////////////
180 class VLCEnumConnectionPoints : public IEnumConnectionPoints
183 VLCEnumConnectionPoints(vector<LPCONNECTIONPOINT> &v) :
184 e(VLCEnum<LPCONNECTIONPOINT>(IID_IEnumConnectionPoints, v))
185 { e.setRetainOperation((VLCEnum<LPCONNECTIONPOINT>::retainer)&retain); };
187 VLCEnumConnectionPoints(const VLCEnumConnectionPoints &vlcEnum) : e(vlcEnum.e) {};
189 virtual ~VLCEnumConnectionPoints() {};
192 STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
193 { return e.QueryInterface(riid, ppv); };
194 STDMETHODIMP_(ULONG) AddRef(void)
195 { return e.AddRef(); };
196 STDMETHODIMP_(ULONG) Release(void)
197 {return e.Release(); };
199 //IEnumConnectionPoints
200 STDMETHODIMP Next(ULONG celt, LPCONNECTIONPOINT *rgelt, ULONG *pceltFetched)
201 { return e.Next(celt, rgelt, pceltFetched); };
202 STDMETHODIMP Skip(ULONG celt)
203 { return e.Skip(celt);};
204 STDMETHODIMP Reset(void)
205 { return e.Reset();};
206 STDMETHODIMP Clone(LPENUMCONNECTIONPOINTS *ppenum)
207 { if( NULL == ppenum ) return E_POINTER;
208 *ppenum = dynamic_cast<LPENUMCONNECTIONPOINTS>(new VLCEnumConnectionPoints(*this));
209 return (NULL != *ppenum) ? S_OK : E_OUTOFMEMORY;
214 static void retain(LPCONNECTIONPOINT cp)
219 VLCEnum<LPCONNECTIONPOINT> e;
222 ////////////////////////////////////////////////////////////////////////////////////////////////
224 VLCDispatchEvent::~VLCDispatchEvent()
226 //clear event arguments
227 if( NULL != _dispParams.rgvarg )
229 for(unsigned int c=0; c<_dispParams.cArgs; ++c)
230 VariantClear(_dispParams.rgvarg+c);
231 CoTaskMemFree(_dispParams.rgvarg);
233 if( NULL != _dispParams.rgdispidNamedArgs )
234 CoTaskMemFree(_dispParams.rgdispidNamedArgs);
237 ////////////////////////////////////////////////////////////////////////////////////////////////
239 VLCConnectionPointContainer::VLCConnectionPointContainer(VLCPlugin *p_instance) :
240 _p_instance(p_instance), _b_freeze(FALSE)
242 _p_events = new VLCConnectionPoint(dynamic_cast<LPCONNECTIONPOINTCONTAINER>(this),
243 _p_instance->getDispEventID());
245 _v_cps.push_back(dynamic_cast<LPCONNECTIONPOINT>(_p_events));
247 _p_props = new VLCConnectionPoint(dynamic_cast<LPCONNECTIONPOINTCONTAINER>(this),
248 IID_IPropertyNotifySink);
250 _v_cps.push_back(dynamic_cast<LPCONNECTIONPOINT>(_p_props));
253 VLCConnectionPointContainer::~VLCConnectionPointContainer()
259 STDMETHODIMP VLCConnectionPointContainer::EnumConnectionPoints(LPENUMCONNECTIONPOINTS *ppEnum)
264 *ppEnum = dynamic_cast<LPENUMCONNECTIONPOINTS>(new VLCEnumConnectionPoints(_v_cps));
266 return (NULL != *ppEnum ) ? S_OK : E_OUTOFMEMORY;
269 STDMETHODIMP VLCConnectionPointContainer::FindConnectionPoint(REFIID riid, IConnectionPoint **ppCP)
276 if( IID_IPropertyNotifySink == riid )
279 *ppCP = dynamic_cast<LPCONNECTIONPOINT>(_p_props);
281 else if( _p_instance->getDispEventID() == riid )
284 *ppCP = dynamic_cast<LPCONNECTIONPOINT>(_p_events);
287 return CONNECT_E_NOCONNECTION;
292 void VLCConnectionPointContainer::freezeEvents(BOOL freeze)
296 // release queued events
297 while( ! _q_events.empty() )
299 VLCDispatchEvent *ev = _q_events.front();
301 _p_events->fireEvent(ev->_dispId, &ev->_dispParams);
308 void VLCConnectionPointContainer::fireEvent(DISPID dispId, DISPPARAMS* pDispParams)
312 // queue event for later use when container is ready
313 _q_events.push(new VLCDispatchEvent(dispId, *pDispParams));
314 if( _q_events.size() > 10 )
316 // too many events in queue, get rid of older one
317 delete _q_events.front();
323 _p_events->fireEvent(dispId, pDispParams);
327 void VLCConnectionPointContainer::firePropChangedEvent(DISPID dispId)
330 _p_props->firePropChangedEvent(dispId);