msdaps: Add server side stubs for IAccessor.
[wine] / dlls / qedit / samplegrabber.c
1 /*              DirectShow Sample Grabber object (QEDIT.DLL)
2  *
3  * Copyright 2009 Paul Chitescu
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19
20 #include <assert.h>
21 #include <stdarg.h>
22
23 #define COBJMACROS
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winuser.h"
28 #include "ole2.h"
29
30 #include "qedit_private.h"
31 #include "wine/debug.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(qedit);
34
35 static WCHAR const vendor_name[] = { 'W', 'i', 'n', 'e', 0 };
36
37 /* Sample Grabber filter implementation */
38 typedef struct _SG_Impl {
39     const IBaseFilterVtbl* IBaseFilter_Vtbl;
40     const ISampleGrabberVtbl* ISampleGrabber_Vtbl;
41     /* TODO: IMediaPosition, IMediaSeeking, IQualityControl */
42     LONG refCount;
43     FILTER_INFO info;
44     FILTER_STATE state;
45     IMemAllocator *allocator;
46     IReferenceClock *refClock;
47 } SG_Impl;
48
49 /* Get the SampleGrabber implementation This pointer from various interface pointers */
50 static inline SG_Impl *impl_from_IBaseFilter(IBaseFilter *iface)
51 {
52     return (SG_Impl *)((char*)iface - FIELD_OFFSET(SG_Impl, IBaseFilter_Vtbl));
53 }
54
55 static inline SG_Impl *impl_from_ISampleGrabber(ISampleGrabber *iface)
56 {
57     return (SG_Impl *)((char*)iface - FIELD_OFFSET(SG_Impl, ISampleGrabber_Vtbl));
58 }
59
60
61 /* Cleanup at end of life */
62 static void SampleGrabber_cleanup(SG_Impl *This)
63 {
64     TRACE("(%p)\n", This);
65     if (This->info.pGraph)
66         WARN("(%p) still joined to filter graph %p\n", This, This->info.pGraph);
67     if (This->allocator)
68         IMemAllocator_Release(This->allocator);
69     if (This->refClock)
70         IReferenceClock_Release(This->refClock);
71 }
72
73 /* Common helper AddRef called from all interfaces */
74 static ULONG SampleGrabber_addref(SG_Impl *This)
75 {
76     ULONG refCount = InterlockedIncrement(&This->refCount);
77     TRACE("(%p) new ref = %u\n", This, refCount);
78     return refCount;
79 }
80
81 /* Common helper Release called from all interfaces */
82 static ULONG SampleGrabber_release(SG_Impl *This)
83 {
84     ULONG refCount = InterlockedDecrement(&This->refCount);
85     TRACE("(%p) new ref = %u\n", This, refCount);
86     if (refCount == 0)
87     {
88         SampleGrabber_cleanup(This);
89         CoTaskMemFree(This);
90         return 0;
91     }
92     return refCount;
93 }
94
95 /* Common helper QueryInterface called from all interfaces */
96 static HRESULT SampleGrabber_query(SG_Impl *This, REFIID riid, void **ppvObject)
97 {
98     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
99
100     if (IsEqualIID(riid, &IID_IUnknown) ||
101         IsEqualIID(riid, &IID_IPersist) ||
102         IsEqualIID(riid, &IID_IMediaFilter) ||
103         IsEqualIID(riid, &IID_IBaseFilter)) {
104         SampleGrabber_addref(This);
105         *ppvObject = &(This->IBaseFilter_Vtbl);
106         return S_OK;
107     }
108     else if (IsEqualIID(riid, &IID_ISampleGrabber)) {
109         SampleGrabber_addref(This);
110         *ppvObject = &(This->ISampleGrabber_Vtbl);
111         return S_OK;
112     }
113     else if (IsEqualIID(riid, &IID_IMemInputPin))
114         FIXME("IMemInputPin not implemented\n");
115     else if (IsEqualIID(riid, &IID_IMediaPosition))
116         FIXME("IMediaPosition not implemented\n");
117     else if (IsEqualIID(riid, &IID_IMediaSeeking))
118         FIXME("IMediaSeeking not implemented\n");
119     else if (IsEqualIID(riid, &IID_IQualityControl))
120         FIXME("IQualityControl not implemented\n");
121     *ppvObject = NULL;
122     WARN("(%p, %s,%p): not found\n", This, debugstr_guid(riid), ppvObject);
123     return E_NOINTERFACE;
124 }
125
126
127 /* SampleGrabber implementation of IBaseFilter interface */
128
129 /* IUnknown */
130 static HRESULT WINAPI
131 SampleGrabber_IBaseFilter_QueryInterface(IBaseFilter *iface, REFIID riid, void **ppvObject)
132 {
133     return SampleGrabber_query(impl_from_IBaseFilter(iface), riid, ppvObject);
134 }
135
136 /* IUnknown */
137 static ULONG WINAPI
138 SampleGrabber_IBaseFilter_AddRef(IBaseFilter *iface)
139 {
140     return SampleGrabber_addref(impl_from_IBaseFilter(iface));
141 }
142
143 /* IUnknown */
144 static ULONG WINAPI
145 SampleGrabber_IBaseFilter_Release(IBaseFilter *iface)
146 {
147     return SampleGrabber_release(impl_from_IBaseFilter(iface));
148 }
149
150 /* IPersist */
151 static HRESULT WINAPI
152 SampleGrabber_IBaseFilter_GetClassID(IBaseFilter *iface, CLSID *pClassID)
153 {
154     TRACE("(%p)\n", pClassID);
155     if (!pClassID)
156         return E_POINTER;
157     *pClassID = CLSID_SampleGrabber;
158     return S_OK;
159 }
160
161 /* IMediaFilter */
162 static HRESULT WINAPI
163 SampleGrabber_IBaseFilter_Stop(IBaseFilter *iface)
164 {
165     SG_Impl *This = impl_from_IBaseFilter(iface);
166     TRACE("(%p)\n", This);
167     This->state = State_Stopped;
168     return S_OK;
169 }
170
171 /* IMediaFilter */
172 static HRESULT WINAPI
173 SampleGrabber_IBaseFilter_Pause(IBaseFilter *iface)
174 {
175     SG_Impl *This = impl_from_IBaseFilter(iface);
176     TRACE("(%p)\n", This);
177     This->state = State_Paused;
178     return S_OK;
179 }
180
181 /* IMediaFilter */
182 static HRESULT WINAPI
183 SampleGrabber_IBaseFilter_Run(IBaseFilter *iface, REFERENCE_TIME tStart)
184 {
185     SG_Impl *This = impl_from_IBaseFilter(iface);
186     TRACE("(%p)\n", This);
187     This->state = State_Running;
188     return S_OK;
189 }
190
191 /* IMediaFilter */
192 static HRESULT WINAPI
193 SampleGrabber_IBaseFilter_GetState(IBaseFilter *iface, DWORD msTout, FILTER_STATE *state)
194 {
195     SG_Impl *This = impl_from_IBaseFilter(iface);
196     TRACE("(%p)->(%u, %p)\n", This, msTout, state);
197     if (!state)
198         return E_POINTER;
199     *state = This->state;
200     return S_OK;
201 }
202
203 /* IMediaFilter */
204 static HRESULT WINAPI
205 SampleGrabber_IBaseFilter_SetSyncSource(IBaseFilter *iface, IReferenceClock *clock)
206 {
207     SG_Impl *This = impl_from_IBaseFilter(iface);
208     TRACE("(%p)->(%p)\n", This, clock);
209     if (clock != This->refClock)
210     {
211         if (clock)
212             IReferenceClock_AddRef(clock);
213         if (This->refClock)
214             IReferenceClock_Release(This->refClock);
215         This->refClock = clock;
216     }
217     return S_OK;
218 }
219
220 /* IMediaFilter */
221 static HRESULT WINAPI
222 SampleGrabber_IBaseFilter_GetSyncSource(IBaseFilter *iface, IReferenceClock **clock)
223 {
224     SG_Impl *This = impl_from_IBaseFilter(iface);
225     TRACE("(%p)->(%p)\n", This, clock);
226     if (!clock)
227         return E_POINTER;
228     if (This->refClock)
229         IReferenceClock_AddRef(This->refClock);
230     *clock = This->refClock;
231     return S_OK;
232 }
233
234 /* IBaseFilter */
235 static HRESULT WINAPI
236 SampleGrabber_IBaseFilter_EnumPins(IBaseFilter *iface, IEnumPins **pins)
237 {
238     SG_Impl *This = impl_from_IBaseFilter(iface);
239     FIXME("(%p)->(%p): stub\n", This, pins);
240     if (!pins)
241         return E_POINTER;
242     return E_OUTOFMEMORY;
243 }
244
245 /* IBaseFilter */
246 static HRESULT WINAPI
247 SampleGrabber_IBaseFilter_FindPin(IBaseFilter *iface, LPCWSTR id, IPin **pin)
248 {
249     SG_Impl *This = impl_from_IBaseFilter(iface);
250     FIXME("(%p)->(%s, %p): stub\n", This, debugstr_w(id), pin);
251     if (!id || !pin)
252         return E_POINTER;
253     *pin = NULL;
254     return VFW_E_NOT_FOUND;
255 }
256
257 /* IBaseFilter */
258 static HRESULT WINAPI
259 SampleGrabber_IBaseFilter_QueryFilterInfo(IBaseFilter *iface, FILTER_INFO *info)
260 {
261     SG_Impl *This = impl_from_IBaseFilter(iface);
262     TRACE("(%p)->(%p)\n", This, info);
263     if (!info)
264         return E_POINTER;
265     if (This->info.pGraph)
266         IFilterGraph_AddRef(This->info.pGraph);
267     *info = This->info;
268     return S_OK;
269 }
270
271 /* IBaseFilter */
272 static HRESULT WINAPI
273 SampleGrabber_IBaseFilter_JoinFilterGraph(IBaseFilter *iface, IFilterGraph *graph, LPCWSTR name)
274 {
275     SG_Impl *This = impl_from_IBaseFilter(iface);
276     TRACE("(%p)->(%p, %s)\n", This, graph, debugstr_w(name));
277     This->info.pGraph = graph;
278     if (name)
279         lstrcpynW(This->info.achName,name,MAX_FILTER_NAME);
280     return S_OK;
281 }
282
283 /* IBaseFilter */
284 static HRESULT WINAPI
285 SampleGrabber_IBaseFilter_QueryVendorInfo(IBaseFilter *iface, LPWSTR *vendor)
286 {
287     TRACE("(%p)\n", vendor);
288     if (!vendor)
289         return E_POINTER;
290     *vendor = CoTaskMemAlloc(sizeof(vendor_name));
291     CopyMemory(*vendor, vendor_name, sizeof(vendor_name));
292     return S_OK;
293 }
294
295
296 /* SampleGrabber implementation of ISampleGrabber interface */
297
298 /* IUnknown */
299 static HRESULT WINAPI
300 SampleGrabber_ISampleGrabber_QueryInterface(ISampleGrabber *iface, REFIID riid, void **ppvObject)
301 {
302     return SampleGrabber_query(impl_from_ISampleGrabber(iface), riid, ppvObject);
303 }
304
305 /* IUnknown */
306 static ULONG WINAPI
307 SampleGrabber_ISampleGrabber_AddRef(ISampleGrabber *iface)
308 {
309     return SampleGrabber_addref(impl_from_ISampleGrabber(iface));
310 }
311
312 /* IUnknown */
313 static ULONG WINAPI
314 SampleGrabber_ISampleGrabber_Release(ISampleGrabber *iface)
315 {
316     return SampleGrabber_release(impl_from_ISampleGrabber(iface));
317 }
318
319 /* ISampleGrabber */
320 static HRESULT WINAPI
321 SampleGrabber_ISampleGrabber_SetOneShot(ISampleGrabber *iface, BOOL oneShot)
322 {
323     SG_Impl *This = impl_from_ISampleGrabber(iface);
324     FIXME("(%p)->(%u): stub\n", This, oneShot);
325     return E_NOTIMPL;
326 }
327
328 /* ISampleGrabber */
329 static HRESULT WINAPI
330 SampleGrabber_ISampleGrabber_SetMediaType(ISampleGrabber *iface, const AM_MEDIA_TYPE *type)
331 {
332     SG_Impl *This = impl_from_ISampleGrabber(iface);
333     FIXME("(%p)->(%p): stub\n", This, type);
334     if (!type)
335         return E_POINTER;
336     return E_NOTIMPL;
337 }
338
339 /* ISampleGrabber */
340 static HRESULT WINAPI
341 SampleGrabber_ISampleGrabber_GetConnectedMediaType(ISampleGrabber *iface, AM_MEDIA_TYPE *type)
342 {
343     SG_Impl *This = impl_from_ISampleGrabber(iface);
344     FIXME("(%p)->(%p): stub\n", This, type);
345     if (!type)
346         return E_POINTER;
347     return E_NOTIMPL;
348 }
349
350 /* ISampleGrabber */
351 static HRESULT WINAPI
352 SampleGrabber_ISampleGrabber_SetBufferSamples(ISampleGrabber *iface, BOOL bufferEm)
353 {
354     TRACE("(%u)\n", bufferEm);
355     if (bufferEm) {
356         FIXME("buffering not implemented\n");
357         return E_NOTIMPL;
358     }
359     return S_OK;
360 }
361
362 /* ISampleGrabber */
363 static HRESULT WINAPI
364 SampleGrabber_ISampleGrabber_GetCurrentBuffer(ISampleGrabber *iface, LONG *bufSize, LONG *buffer)
365 {
366     FIXME("(%p, %p): stub\n", bufSize, buffer);
367     if (!bufSize)
368         return E_POINTER;
369     return E_INVALIDARG;
370 }
371
372 /* ISampleGrabber */
373 static HRESULT WINAPI
374 SampleGrabber_ISampleGrabber_GetCurrentSample(ISampleGrabber *iface, IMediaSample **sample)
375 {
376     /* MS doesn't implement it either, noone should call it */
377     WARN("(%p): not implemented\n", sample);
378     return E_NOTIMPL;
379 }
380
381 /* ISampleGrabber */
382 static HRESULT WINAPI
383 SampleGrabber_ISampleGrabber_SetCallback(ISampleGrabber *iface, ISampleGrabberCB *cb, LONG whichMethod)
384 {
385     SG_Impl *This = impl_from_ISampleGrabber(iface);
386     FIXME("(%p)->(%p, %u): stub\n", This, cb, whichMethod);
387     return E_NOTIMPL;
388 }
389
390
391 /* SampleGrabber vtables and constructor */
392
393 static const IBaseFilterVtbl IBaseFilter_VTable =
394 {
395     SampleGrabber_IBaseFilter_QueryInterface,
396     SampleGrabber_IBaseFilter_AddRef,
397     SampleGrabber_IBaseFilter_Release,
398     SampleGrabber_IBaseFilter_GetClassID,
399     SampleGrabber_IBaseFilter_Stop,
400     SampleGrabber_IBaseFilter_Pause,
401     SampleGrabber_IBaseFilter_Run,
402     SampleGrabber_IBaseFilter_GetState,
403     SampleGrabber_IBaseFilter_SetSyncSource,
404     SampleGrabber_IBaseFilter_GetSyncSource,
405     SampleGrabber_IBaseFilter_EnumPins,
406     SampleGrabber_IBaseFilter_FindPin,
407     SampleGrabber_IBaseFilter_QueryFilterInfo,
408     SampleGrabber_IBaseFilter_JoinFilterGraph,
409     SampleGrabber_IBaseFilter_QueryVendorInfo,
410 };
411
412 static const ISampleGrabberVtbl ISampleGrabber_VTable =
413 {
414     SampleGrabber_ISampleGrabber_QueryInterface,
415     SampleGrabber_ISampleGrabber_AddRef,
416     SampleGrabber_ISampleGrabber_Release,
417     SampleGrabber_ISampleGrabber_SetOneShot,
418     SampleGrabber_ISampleGrabber_SetMediaType,
419     SampleGrabber_ISampleGrabber_GetConnectedMediaType,
420     SampleGrabber_ISampleGrabber_SetBufferSamples,
421     SampleGrabber_ISampleGrabber_GetCurrentBuffer,
422     SampleGrabber_ISampleGrabber_GetCurrentSample,
423     SampleGrabber_ISampleGrabber_SetCallback,
424 };
425
426 HRESULT SampleGrabber_create(IUnknown *pUnkOuter, LPVOID *ppv)
427 {
428     SG_Impl* obj = NULL;
429
430     TRACE("(%p,%p)\n", ppv, pUnkOuter);
431
432     if (pUnkOuter)
433         return CLASS_E_NOAGGREGATION;
434
435     obj = CoTaskMemAlloc(sizeof(SG_Impl));
436     if (NULL == obj) {
437         *ppv = NULL;
438         return E_OUTOFMEMORY;
439     }
440     ZeroMemory(obj, sizeof(SG_Impl));
441
442     obj->refCount = 1;
443     obj->IBaseFilter_Vtbl = &IBaseFilter_VTable;
444     obj->ISampleGrabber_Vtbl = &ISampleGrabber_VTable;
445     obj->info.achName[0] = 0;
446     obj->info.pGraph = NULL;
447     obj->state = State_Stopped;
448     obj->allocator = NULL;
449     obj->refClock = NULL;
450     *ppv = obj;
451
452     return S_OK;
453 }