]> git.sesse.net Git - vlc/blob - activex/connectioncontainer.cpp
Initial version of ActiveX plugin for VLC
[vlc] / activex / connectioncontainer.cpp
1 /*****************************************************************************\r
2  * connectioncontainer.cpp: ActiveX control for VLC\r
3  *****************************************************************************\r
4  * Copyright (C) 2005 VideoLAN\r
5  *\r
6  * Authors: Damien Fouilleul <Damien.Fouilleul@laposte.net>\r
7  *\r
8  * This program is free software; you can redistribute it and/or modify\r
9  * it under the terms of the GNU General Public License as published by\r
10  * the Free Software Foundation; either version 2 of the License, or\r
11  * (at your option) any later version.\r
12  *\r
13  * This program is distributed in the hope that it will be useful,\r
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
16  * GNU General Public License for more details.\r
17  *\r
18  * You should have received a copy of the GNU General Public License\r
19  * along with this program; if not, write to the Free Software\r
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.\r
21  *****************************************************************************/\r
22 \r
23 #include "plugin.h"\r
24 #include "connectioncontainer.h"\r
25 \r
26 #include "utils.h"\r
27 \r
28 using namespace std;\r
29 \r
30 ////////////////////////////////////////////////////////////////////////////////////////////////\r
31 \r
32 class VLCEnumConnections : public IEnumConnections\r
33 {\r
34 public:\r
35     VLCEnumConnections(vector<CONNECTDATA> &v) :\r
36         e(VLCEnum<CONNECTDATA>(IID_IEnumConnections, v))\r
37     { e.setRetainOperation((VLCEnum<CONNECTDATA>::retainer)&retain); };\r
38 \r
39     VLCEnumConnections(const VLCEnumConnections &vlcEnum) : e(vlcEnum.e) {};\r
40 \r
41     virtual ~VLCEnumConnections() {};\r
42 \r
43     // IUnknown methods\r
44     STDMETHODIMP QueryInterface(REFIID riid, void **ppv)\r
45         { return e.QueryInterface(riid, ppv); };\r
46     STDMETHODIMP_(ULONG) AddRef(void)\r
47         { return e.AddRef(); };\r
48     STDMETHODIMP_(ULONG) Release(void)\r
49         {return e.Release(); };\r
50 \r
51     //IEnumConnectionPoints\r
52     STDMETHODIMP Next(ULONG celt, LPCONNECTDATA rgelt, ULONG *pceltFetched)\r
53         { return e.Next(celt, rgelt, pceltFetched); };\r
54     STDMETHODIMP Skip(ULONG celt)\r
55         { return e.Skip(celt);};\r
56     STDMETHODIMP Reset(void)\r
57         { return e.Reset();};\r
58     STDMETHODIMP Clone(LPENUMCONNECTIONS *ppenum)\r
59         { if( NULL == ppenum ) return E_POINTER;\r
60           *ppenum = dynamic_cast<LPENUMCONNECTIONS>(new VLCEnumConnections(*this));\r
61           return (NULL != *ppenum) ? S_OK : E_OUTOFMEMORY;\r
62         };\r
63 \r
64 private:\r
65 \r
66     static void retain(CONNECTDATA cd)\r
67     {\r
68         cd.pUnk->AddRef();\r
69     };\r
70 \r
71     VLCEnum<CONNECTDATA> e;\r
72 };\r
73 \r
74 ////////////////////////////////////////////////////////////////////////////////////////////////\r
75 \r
76 STDMETHODIMP VLCConnectionPoint::GetConnectionInterface(IID *iid)\r
77 {\r
78     if( NULL == iid )\r
79         return E_POINTER;\r
80 \r
81     *iid = _iid;\r
82     return S_OK;\r
83 };\r
84 \r
85 STDMETHODIMP VLCConnectionPoint::GetConnectionPointContainer(LPCONNECTIONPOINTCONTAINER *ppCPC)\r
86 {\r
87     if( NULL == ppCPC )\r
88         return E_POINTER;\r
89 \r
90     _p_cpc->AddRef();\r
91     *ppCPC = _p_cpc;\r
92     return S_OK;\r
93 };\r
94 \r
95 STDMETHODIMP VLCConnectionPoint::Advise(IUnknown *pUnk, DWORD *pdwCookie)\r
96 {\r
97     if( (NULL == pUnk) || (NULL == pdwCookie) )\r
98         return E_POINTER;\r
99 \r
100     CONNECTDATA cd;\r
101 \r
102     pUnk->AddRef();\r
103     cd.pUnk = pUnk;\r
104     *pdwCookie = cd.dwCookie = _connections.size();\r
105 \r
106     _connections.push_back(cd);\r
107 \r
108     return S_OK;\r
109 };\r
110 \r
111 STDMETHODIMP VLCConnectionPoint::Unadvise(DWORD pdwCookie)\r
112 {\r
113     if( pdwCookie < _connections.size() )\r
114     {\r
115         CONNECTDATA cd = _connections[pdwCookie];\r
116         if( NULL != cd.pUnk )\r
117         {\r
118             cd.pUnk->Release();\r
119             cd.pUnk = NULL;\r
120             return S_OK;\r
121         }\r
122     }\r
123     return CONNECT_E_NOCONNECTION;\r
124 };\r
125 \r
126 STDMETHODIMP VLCConnectionPoint::EnumConnections(IEnumConnections **ppEnum)\r
127 {\r
128     if( NULL == ppEnum )\r
129         return E_POINTER;\r
130 \r
131     *ppEnum = dynamic_cast<LPENUMCONNECTIONS>(new VLCEnumConnections(_connections));\r
132 \r
133     return (NULL != *ppEnum ) ? S_OK : E_OUTOFMEMORY;\r
134 };\r
135 \r
136 void VLCConnectionPoint::fireEvent(DISPID dispId, LCID lcid, DISPPARAMS* pDispParams)\r
137 {\r
138     vector<CONNECTDATA>::iterator end = _connections.end();\r
139     vector<CONNECTDATA>::iterator iter = _connections.begin();\r
140 \r
141     while( iter != end )\r
142     {\r
143         CONNECTDATA cd = *iter;\r
144         if( NULL != cd.pUnk )\r
145         {\r
146             IDispatch *pDisp;\r
147             if( SUCCEEDED(cd.pUnk->QueryInterface(IID_IDispatch, (LPVOID *)&pDisp)) )\r
148             {\r
149                 unsigned int puArgErr;\r
150                 VARIANT vRes;\r
151 \r
152                 if( SUCCEEDED(pDisp->Invoke(dispId, IID_NULL, lcid, DISPATCH_METHOD, pDispParams, &vRes, NULL, &puArgErr)) )\r
153                 {\r
154                     VariantClear(&vRes);\r
155                 }\r
156                 pDisp->Release();\r
157             }\r
158         }\r
159         ++iter;\r
160     }\r
161 };\r
162 \r
163 void VLCConnectionPoint::firePropChangedEvent(DISPID dispId)\r
164 {\r
165     vector<CONNECTDATA>::iterator end = _connections.end();\r
166     vector<CONNECTDATA>::iterator iter = _connections.begin();\r
167 \r
168     while( iter != end )\r
169     {\r
170         CONNECTDATA cd = *iter;\r
171         if( NULL != cd.pUnk )\r
172         {\r
173             IPropertyNotifySink *pPropSink;\r
174             if( SUCCEEDED(cd.pUnk->QueryInterface(IID_IPropertyNotifySink, (LPVOID *)&pPropSink)) )\r
175             {\r
176                 pPropSink->OnChanged(dispId);\r
177                 pPropSink->Release();\r
178             }\r
179         }\r
180         ++iter;\r
181     }\r
182 };\r
183 \r
184 ////////////////////////////////////////////////////////////////////////////////////////////////\r
185 \r
186 class VLCEnumConnectionPoints : public IEnumConnectionPoints\r
187 {\r
188 public:\r
189     VLCEnumConnectionPoints(vector<LPCONNECTIONPOINT> &v) :\r
190         e(VLCEnum<LPCONNECTIONPOINT>(IID_IEnumConnectionPoints, v))\r
191     { e.setRetainOperation((VLCEnum<LPCONNECTIONPOINT>::retainer)&retain); };\r
192 \r
193     VLCEnumConnectionPoints(const VLCEnumConnectionPoints &vlcEnum) : e(vlcEnum.e) {};\r
194 \r
195     virtual ~VLCEnumConnectionPoints() {};\r
196 \r
197     // IUnknown methods\r
198     STDMETHODIMP QueryInterface(REFIID riid, void **ppv)\r
199         { return e.QueryInterface(riid, ppv); };\r
200     STDMETHODIMP_(ULONG) AddRef(void)\r
201         { return e.AddRef(); };\r
202     STDMETHODIMP_(ULONG) Release(void)\r
203         {return e.Release(); };\r
204 \r
205     //IEnumConnectionPoints\r
206     STDMETHODIMP Next(ULONG celt, LPCONNECTIONPOINT *rgelt, ULONG *pceltFetched)\r
207         { return e.Next(celt, rgelt, pceltFetched); };\r
208     STDMETHODIMP Skip(ULONG celt)\r
209         { return e.Skip(celt);};\r
210     STDMETHODIMP Reset(void)\r
211         { return e.Reset();};\r
212     STDMETHODIMP Clone(LPENUMCONNECTIONPOINTS *ppenum)\r
213         { if( NULL == ppenum ) return E_POINTER;\r
214           *ppenum = dynamic_cast<LPENUMCONNECTIONPOINTS>(new VLCEnumConnectionPoints(*this));\r
215           return (NULL != *ppenum) ? S_OK : E_OUTOFMEMORY;\r
216         };\r
217 \r
218 private:\r
219 \r
220     static void retain(LPCONNECTIONPOINT cp)\r
221     {\r
222         cp->AddRef();\r
223     };\r
224 \r
225     VLCEnum<LPCONNECTIONPOINT> e;\r
226 };\r
227 \r
228 ////////////////////////////////////////////////////////////////////////////////////////////////\r
229 \r
230 VLCConnectionPointContainer::VLCConnectionPointContainer(VLCPlugin *p_instance) :\r
231     _p_instance(p_instance)\r
232 {\r
233     _p_events = new VLCConnectionPoint(dynamic_cast<LPCONNECTIONPOINTCONTAINER>(this),\r
234             _p_instance->getDispEventID());\r
235 \r
236     _v_cps.push_back(dynamic_cast<LPCONNECTIONPOINT>(_p_events));\r
237 \r
238     _p_props = new VLCConnectionPoint(dynamic_cast<LPCONNECTIONPOINTCONTAINER>(this),\r
239             IID_IPropertyNotifySink);\r
240 \r
241     _v_cps.push_back(dynamic_cast<LPCONNECTIONPOINT>(_p_props));\r
242 };\r
243 \r
244 VLCConnectionPointContainer::~VLCConnectionPointContainer()\r
245 {\r
246     _v_cps.clear();\r
247     delete _p_props;\r
248     delete _p_events;\r
249 };\r
250 \r
251 STDMETHODIMP VLCConnectionPointContainer::EnumConnectionPoints(LPENUMCONNECTIONPOINTS *ppEnum)\r
252 {\r
253     if( NULL == ppEnum )\r
254         return E_POINTER;\r
255 \r
256     *ppEnum = dynamic_cast<LPENUMCONNECTIONPOINTS>(new VLCEnumConnectionPoints(_v_cps));\r
257 \r
258     return (NULL != *ppEnum ) ? S_OK : E_OUTOFMEMORY;\r
259 };\r
260 \r
261 STDMETHODIMP VLCConnectionPointContainer::FindConnectionPoint(REFIID riid, IConnectionPoint **ppCP)\r
262 {\r
263     if( NULL == ppCP )\r
264         return E_POINTER;\r
265 \r
266     *ppCP = NULL;\r
267 \r
268     if( IID_IPropertyNotifySink == riid )\r
269     {\r
270         _p_props->AddRef();\r
271         *ppCP = dynamic_cast<LPCONNECTIONPOINT>(_p_props);\r
272     }\r
273     else if( _p_instance->getDispEventID() == riid )\r
274     {\r
275         _p_events->AddRef();\r
276         *ppCP = dynamic_cast<LPCONNECTIONPOINT>(_p_events);\r
277     }\r
278     else\r
279         return CONNECT_E_NOCONNECTION;\r
280 \r
281     return NOERROR;\r
282 };\r
283 \r
284 void VLCConnectionPointContainer::fireEvent(DISPID dispId, LCID lcid, DISPPARAMS* pDispParams)\r
285 {\r
286     _p_events->fireEvent(dispId,lcid, pDispParams);\r
287 };\r
288 \r
289 void VLCConnectionPointContainer::firePropChangedEvent(DISPID dispId)\r
290 {\r
291     _p_props->firePropChangedEvent(dispId);\r
292 };\r
293 \r