wmp: Implement IConnectionPoint[Container] and add _WMPOCXEvents.
[wine.git] / dlls / wmp / events.c
bloba908834010ded76d349253c61029b141bbfcb2b8
1 /*
2 * Implementation of event-related interfaces for WMP control:
4 * - IConnectionPointContainer
5 * - IConnectionPoint
7 * Copyright 2001 John R. Sheets (for CodeWeavers)
8 * Copyright 2006 Jacek Caban for CodeWeavers
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "wmp_private.h"
26 #include "olectl.h"
27 #include "wine/debug.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(wmp);
31 static inline WindowsMediaPlayer *impl_from_IConnectionPointContainer(IConnectionPointContainer *iface)
33 return CONTAINING_RECORD(iface, WindowsMediaPlayer, IConnectionPointContainer_iface);
36 static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface,
37 REFIID riid, LPVOID *ppv)
39 WindowsMediaPlayer *This = impl_from_IConnectionPointContainer(iface);
40 return IOleObject_QueryInterface(&This->IOleObject_iface, riid, ppv);
43 static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface)
45 WindowsMediaPlayer *This = impl_from_IConnectionPointContainer(iface);
46 return IOleObject_AddRef(&This->IOleObject_iface);
49 static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface)
51 WindowsMediaPlayer *This = impl_from_IConnectionPointContainer(iface);
52 return IOleObject_Release(&This->IOleObject_iface);
55 static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface,
56 IEnumConnectionPoints **ppEnum)
58 WindowsMediaPlayer *This = impl_from_IConnectionPointContainer(iface);
59 FIXME("(%p)->(%p)\n", This, ppEnum);
60 return E_NOTIMPL;
63 static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface,
64 REFIID riid, IConnectionPoint **ppCP){
65 WindowsMediaPlayer *This = impl_from_IConnectionPointContainer(iface);
67 if(!ppCP) {
68 WARN("ppCP == NULL\n");
69 return E_POINTER;
72 *ppCP = NULL;
74 if(IsEqualGUID(&IID__WMPOCXEvents, riid)) {
75 TRACE("(%p)->(IID__WMPOCXEvents %p)\n", This, ppCP);
76 *ppCP = &This->wmpocx->IConnectionPoint_iface;
79 if(*ppCP) {
80 IConnectionPoint_AddRef(*ppCP);
81 return S_OK;
84 WARN("Unsupported IID %s\n", debugstr_guid(riid));
85 return CONNECT_E_NOCONNECTION;
88 static const IConnectionPointContainerVtbl ConnectionPointContainerVtbl =
90 ConnectionPointContainer_QueryInterface,
91 ConnectionPointContainer_AddRef,
92 ConnectionPointContainer_Release,
93 ConnectionPointContainer_EnumConnectionPoints,
94 ConnectionPointContainer_FindConnectionPoint
97 static inline ConnectionPoint *impl_from_IConnectionPoint(IConnectionPoint *iface)
99 return CONTAINING_RECORD(iface, ConnectionPoint, IConnectionPoint_iface);
102 typedef struct {
103 IEnumConnections IEnumConnections_iface;
105 LONG ref;
107 ConnectionPoint *cp;
108 DWORD iter;
109 } EnumConnections;
111 static inline EnumConnections *impl_from_IEnumConnections(IEnumConnections *iface)
113 return CONTAINING_RECORD(iface, EnumConnections, IEnumConnections_iface);
116 static HRESULT WINAPI EnumConnections_QueryInterface(IEnumConnections *iface, REFIID riid, void **ppv)
118 EnumConnections *This = impl_from_IEnumConnections(iface);
120 if(IsEqualGUID(&IID_IUnknown, riid)) {
121 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
122 *ppv = &This->IEnumConnections_iface;
123 }else if(IsEqualGUID(&IID_IEnumConnections, riid)) {
124 TRACE("(%p)->(IID_IEnumConnections %p)\n", This, ppv);
125 *ppv = &This->IEnumConnections_iface;
126 }else {
127 WARN("Unsupported interface %s\n", debugstr_guid(riid));
128 *ppv = NULL;
129 return E_NOINTERFACE;
132 IUnknown_AddRef((IUnknown*)*ppv);
133 return S_OK;
136 static ULONG WINAPI EnumConnections_AddRef(IEnumConnections *iface)
138 EnumConnections *This = impl_from_IEnumConnections(iface);
139 LONG ref = InterlockedIncrement(&This->ref);
141 TRACE("(%p) ref=%d\n", This, ref);
143 return ref;
146 static ULONG WINAPI EnumConnections_Release(IEnumConnections *iface)
148 EnumConnections *This = impl_from_IEnumConnections(iface);
149 LONG ref = InterlockedDecrement(&This->ref);
151 TRACE("(%p) ref=%d\n", This, ref);
153 if(!ref) {
154 IConnectionPoint_Release(&This->cp->IConnectionPoint_iface);
155 heap_free(This);
158 return ref;
161 static HRESULT WINAPI EnumConnections_Next(IEnumConnections *iface, ULONG cConnections, CONNECTDATA *pgcd, ULONG *pcFetched)
163 EnumConnections *This = impl_from_IEnumConnections(iface);
164 ULONG cnt = 0;
166 TRACE("(%p)->(%u %p %p)\n", This, cConnections, pgcd, pcFetched);
168 while(cConnections--) {
169 while(This->iter < This->cp->sinks_size && !This->cp->sinks[This->iter])
170 This->iter++;
171 if(This->iter == This->cp->sinks_size)
172 break;
174 pgcd[cnt].pUnk = (IUnknown*)This->cp->sinks[This->iter];
175 pgcd[cnt].dwCookie = cnt+1;
176 This->iter++;
177 cnt++;
178 IUnknown_AddRef(pgcd[cnt].pUnk);
181 if(pcFetched)
182 *pcFetched = cnt;
183 return cnt ? S_OK : S_FALSE;
186 static HRESULT WINAPI EnumConnections_Skip(IEnumConnections *iface, ULONG cConnections)
188 EnumConnections *This = impl_from_IEnumConnections(iface);
189 FIXME("(%p)->(%u)\n", This, cConnections);
190 return E_NOTIMPL;
193 static HRESULT WINAPI EnumConnections_Reset(IEnumConnections *iface)
195 EnumConnections *This = impl_from_IEnumConnections(iface);
196 FIXME("(%p)\n", This);
197 return E_NOTIMPL;
200 static HRESULT WINAPI EnumConnections_Clone(IEnumConnections *iface, IEnumConnections **ppEnum)
202 EnumConnections *This = impl_from_IEnumConnections(iface);
203 FIXME("(%p)->(%p)\n", This, ppEnum);
204 return E_NOTIMPL;
207 static const IEnumConnectionsVtbl EnumConnectionsVtbl = {
208 EnumConnections_QueryInterface,
209 EnumConnections_AddRef,
210 EnumConnections_Release,
211 EnumConnections_Next,
212 EnumConnections_Skip,
213 EnumConnections_Reset,
214 EnumConnections_Clone
217 static HRESULT WINAPI ConnectionPoint_QueryInterface(IConnectionPoint *iface,
218 REFIID riid, LPVOID *ppv)
220 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
222 *ppv = NULL;
224 if(IsEqualGUID(&IID_IUnknown, riid)) {
225 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
226 *ppv = &This->IConnectionPoint_iface;
227 }else if(IsEqualGUID(&IID_IConnectionPoint, riid)) {
228 TRACE("(%p)->(IID_IConnectionPoint %p)\n", This, ppv);
229 *ppv = &This->IConnectionPoint_iface;
232 if(*ppv) {
233 IConnectionPointContainer_AddRef(This->container);
234 return S_OK;
237 WARN("Unsupported interface %s\n", debugstr_guid(riid));
238 return E_NOINTERFACE;
241 static ULONG WINAPI ConnectionPoint_AddRef(IConnectionPoint *iface)
243 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
244 return IConnectionPointContainer_AddRef(This->container);
247 static ULONG WINAPI ConnectionPoint_Release(IConnectionPoint *iface)
249 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
250 return IConnectionPointContainer_Release(This->container);
253 static HRESULT WINAPI ConnectionPoint_GetConnectionInterface(IConnectionPoint *iface, IID *pIID)
255 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
257 TRACE("(%p)->(%p)\n", This, pIID);
259 *pIID = This->iid;
260 return S_OK;
263 static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoint *iface,
264 IConnectionPointContainer **ppCPC)
266 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
268 TRACE("(%p)->(%p)\n", This, ppCPC);
270 *ppCPC = This->container;
271 IConnectionPointContainer_AddRef(This->container);
272 return S_OK;
275 static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *pUnkSink,
276 DWORD *pdwCookie)
278 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
279 IDispatch *disp;
280 DWORD i;
281 HRESULT hres;
283 TRACE("(%p)->(%p %p)\n", This, pUnkSink, pdwCookie);
285 hres = IUnknown_QueryInterface(pUnkSink, &This->iid, (void**)&disp);
286 if(FAILED(hres)) {
287 hres = IUnknown_QueryInterface(pUnkSink, &IID_IDispatch, (void**)&disp);
288 if(FAILED(hres))
289 return CONNECT_E_CANNOTCONNECT;
292 if(This->sinks) {
293 for(i=0; i<This->sinks_size; i++) {
294 if(!This->sinks[i])
295 break;
298 if(i == This->sinks_size)
299 This->sinks = heap_realloc(This->sinks,
300 (++This->sinks_size)*sizeof(*This->sinks));
301 }else {
302 This->sinks = heap_alloc(sizeof(*This->sinks));
303 This->sinks_size = 1;
304 i = 0;
307 This->sinks[i] = disp;
308 *pdwCookie = i+1;
310 return S_OK;
313 static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD dwCookie)
315 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
317 TRACE("(%p)->(%d)\n", This, dwCookie);
319 if(!dwCookie || dwCookie > This->sinks_size || !This->sinks[dwCookie-1])
320 return CONNECT_E_NOCONNECTION;
322 IDispatch_Release(This->sinks[dwCookie-1]);
323 This->sinks[dwCookie-1] = NULL;
325 return S_OK;
328 static HRESULT WINAPI ConnectionPoint_EnumConnections(IConnectionPoint *iface,
329 IEnumConnections **ppEnum)
331 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
332 EnumConnections *ret;
334 TRACE("(%p)->(%p)\n", This, ppEnum);
336 ret = heap_alloc(sizeof(*ret));
337 if(!ret)
338 return E_OUTOFMEMORY;
340 ret->IEnumConnections_iface.lpVtbl = &EnumConnectionsVtbl;
341 ret->ref = 1;
342 ret->iter = 0;
344 IConnectionPoint_AddRef(&This->IConnectionPoint_iface);
345 ret->cp = This;
347 *ppEnum = &ret->IEnumConnections_iface;
348 return S_OK;
352 static const IConnectionPointVtbl ConnectionPointVtbl =
354 ConnectionPoint_QueryInterface,
355 ConnectionPoint_AddRef,
356 ConnectionPoint_Release,
357 ConnectionPoint_GetConnectionInterface,
358 ConnectionPoint_GetConnectionPointContainer,
359 ConnectionPoint_Advise,
360 ConnectionPoint_Unadvise,
361 ConnectionPoint_EnumConnections
364 static void ConnectionPoint_Destroy(ConnectionPoint *This)
366 DWORD i;
368 for(i=0; i<This->sinks_size; i++) {
369 if(This->sinks[i])
370 IDispatch_Release(This->sinks[i]);
373 heap_free(This->sinks);
374 heap_free(This);
377 static void ConnectionPoint_Create(REFIID riid, ConnectionPoint **cp,
378 IConnectionPointContainer *container)
380 ConnectionPoint *ret = heap_alloc(sizeof(ConnectionPoint));
382 ret->IConnectionPoint_iface.lpVtbl = &ConnectionPointVtbl;
384 ret->sinks = NULL;
385 ret->sinks_size = 0;
386 ret->container = container;
388 ret->iid = *riid;
390 *cp = ret;
393 void ConnectionPointContainer_Init(WindowsMediaPlayer *wmp)
395 wmp->IConnectionPointContainer_iface.lpVtbl = &ConnectionPointContainerVtbl;
396 ConnectionPoint_Create(&IID__WMPOCXEvents, &wmp->wmpocx, &wmp->IConnectionPointContainer_iface);
399 void ConnectionPointContainer_Destroy(WindowsMediaPlayer *wmp)
401 ConnectionPoint_Destroy(wmp->wmpocx);