shell32: Have SHELL_ArgifyW respect the length of the buffer passed in and report...
[wine.git] / dlls / qcap / vfwcapture.c
blobace2b55978ced8c687e534c47b86fd40c2eff642
1 /* Video For Windows Steering structure
3 * Copyright 2005 Maarten Lankhorst
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.
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.
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
21 #define NONAMELESSSTRUCT
22 #define NONAMELESSUNION
23 #define COBJMACROS
25 #include "config.h"
26 #include <stdarg.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "wtypes.h"
31 #include "wingdi.h"
32 #include "winuser.h"
33 #include "dshow.h"
35 #include "qcap_main.h"
36 #include "wine/debug.h"
38 #include "pin.h"
39 #include "capture.h"
40 #include "uuids.h"
41 #include "mmreg.h"
42 #include "vfwmsgs.h"
43 #include "amvideo.h"
44 #include "strmif.h"
45 #include "ddraw.h"
46 #include "ocidl.h"
47 #include "oleauto.h"
49 WINE_DEFAULT_DEBUG_CHANNEL(qcap);
51 #define ICOM_THIS_MULTI(impl,field,iface) \
52 impl* const This=(impl*)((char*)(iface) - offsetof(impl,field))
54 static const IBaseFilterVtbl VfwCapture_Vtbl;
55 static const IAMStreamConfigVtbl IAMStreamConfig_VTable;
56 static const IAMVideoProcAmpVtbl IAMVideoProcAmp_VTable;
57 static const IPersistPropertyBagVtbl IPersistPropertyBag_VTable;
58 static const IPinVtbl VfwPin_Vtbl;
60 static HRESULT VfwPin_Construct( IBaseFilter *, LPCRITICAL_SECTION, IPin ** );
62 typedef struct VfwCapture
64 const IBaseFilterVtbl * lpVtbl;
65 const IAMStreamConfigVtbl * IAMStreamConfig_vtbl;
66 const IAMVideoProcAmpVtbl * IAMVideoProcAmp_vtbl;
67 const IPersistPropertyBagVtbl * IPersistPropertyBag_vtbl;
69 BOOL init;
70 Capture *driver_info;
71 LONG refCount;
72 FILTER_INFO filterInfo;
73 FILTER_STATE state;
74 CRITICAL_SECTION csFilter;
76 IPin * pOutputPin;
77 } VfwCapture;
79 /* VfwPin implementation */
80 typedef struct VfwPinImpl
82 OutputPin pin;
83 Capture *driver_info;
84 const IKsPropertySetVtbl * KSP_VT;
85 } VfwPinImpl;
88 IUnknown * WINAPI QCAP_createVFWCaptureFilter(IUnknown *pUnkOuter, HRESULT *phr)
90 VfwCapture *pVfwCapture;
91 HRESULT hr;
93 TRACE("%p - %p\n", pUnkOuter, phr);
95 *phr = CLASS_E_NOAGGREGATION;
96 if (pUnkOuter)
97 return NULL;
98 *phr = E_OUTOFMEMORY;
100 pVfwCapture = CoTaskMemAlloc( sizeof(VfwCapture) );
102 if (!pVfwCapture)
103 return NULL;
105 pVfwCapture->lpVtbl = &VfwCapture_Vtbl;
106 pVfwCapture->IAMStreamConfig_vtbl = &IAMStreamConfig_VTable;
107 pVfwCapture->IAMVideoProcAmp_vtbl = &IAMVideoProcAmp_VTable;
108 pVfwCapture->IPersistPropertyBag_vtbl = &IPersistPropertyBag_VTable;
109 pVfwCapture->refCount = 1;
110 pVfwCapture->filterInfo.achName[0] = '\0';
111 pVfwCapture->filterInfo.pGraph = NULL;
112 pVfwCapture->state = State_Stopped;
113 pVfwCapture->init = FALSE;
114 InitializeCriticalSection(&pVfwCapture->csFilter);
115 hr = VfwPin_Construct((IBaseFilter *)&pVfwCapture->lpVtbl,
116 &pVfwCapture->csFilter, &pVfwCapture->pOutputPin);
117 if (!SUCCEEDED(hr))
119 CoTaskMemFree(pVfwCapture);
120 return NULL;
122 TRACE("-- created at %p\n", pVfwCapture);
124 ObjectRefCount(TRUE);
125 *phr = S_OK;
126 return (IUnknown *)pVfwCapture;
129 static HRESULT WINAPI VfwCapture_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
131 VfwCapture *This = (VfwCapture *)iface;
132 TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
133 *ppv = NULL;
135 if (IsEqualIID(riid, &IID_IUnknown) ||
136 IsEqualIID(riid, &IID_IPersist) ||
137 IsEqualIID(riid, &IID_IMediaFilter) ||
138 IsEqualIID(riid, &IID_IBaseFilter))
140 *ppv = This;
142 else if (IsEqualIID(riid, &IID_IAMStreamConfig))
143 *ppv = &(This->IAMStreamConfig_vtbl);
144 else if (IsEqualIID(riid, &IID_IAMVideoProcAmp))
145 *ppv = &(This->IAMVideoProcAmp_vtbl);
146 else if (IsEqualIID(riid, &IID_IPersistPropertyBag))
147 *ppv = &(This->IPersistPropertyBag_vtbl);
149 if (!IsEqualIID(riid, &IID_IUnknown) &&
150 !IsEqualIID(riid, &IID_IPersist) &&
151 !IsEqualIID(riid, &IID_IPersistPropertyBag) &&
152 !This->init)
154 FIXME("Capture system not initialised when looking for %s, "
155 "trying it on primary device now\n", debugstr_guid(riid));
156 This->driver_info = qcap_driver_init( This->pOutputPin, 0 );
157 if (!This->driver_info)
159 ERR("VfwCapture initialisation failed\n");
160 return E_UNEXPECTED;
162 This->init = TRUE;
165 if (*ppv)
167 TRACE("Returning %s interface\n", debugstr_guid(riid));
168 IUnknown_AddRef((IUnknown *)(*ppv));
169 return S_OK;
172 FIXME("No interface for %s!\n", debugstr_guid(riid));
173 return E_NOINTERFACE;
176 static ULONG WINAPI VfwCapture_AddRef(IBaseFilter * iface)
178 VfwCapture *This = (VfwCapture *)iface;
179 ULONG refCount = InterlockedIncrement(&This->refCount);
181 TRACE("%p->() New refcount: %d\n", This, refCount);
183 return refCount;
186 static ULONG WINAPI VfwCapture_Release(IBaseFilter * iface)
188 VfwCapture *This = (VfwCapture *)iface;
189 ULONG refCount = InterlockedDecrement(&This->refCount);
191 TRACE("%p->() New refcount: %d\n", This, refCount);
193 if (!refCount)
195 IPinImpl *pin;
197 TRACE("destroying everything\n");
198 if (This->init)
200 if (This->state != State_Stopped)
201 qcap_driver_stop(This->driver_info, &This->state);
202 qcap_driver_destroy(This->driver_info);
204 pin = (IPinImpl*) This->pOutputPin;
205 if (pin->pConnectedTo != NULL)
207 IPin_Disconnect(pin->pConnectedTo);
208 IPin_Disconnect(This->pOutputPin);
210 IPin_Release(This->pOutputPin);
211 DeleteCriticalSection(&This->csFilter);
212 This->lpVtbl = NULL;
213 CoTaskMemFree(This);
214 ObjectRefCount(FALSE);
216 return refCount;
219 /** IPersist methods **/
221 static HRESULT WINAPI VfwCapture_GetClassID(IBaseFilter * iface, CLSID * pClsid)
223 TRACE("(%p)\n", pClsid);
224 *pClsid = CLSID_VfwCapture;
225 return S_OK;
228 /** IMediaFilter methods **/
230 static HRESULT WINAPI VfwCapture_Stop(IBaseFilter * iface)
232 VfwCapture *This = (VfwCapture *)iface;
234 TRACE("()\n");
235 return qcap_driver_stop(This->driver_info, &This->state);
238 static HRESULT WINAPI VfwCapture_Pause(IBaseFilter * iface)
240 VfwCapture *This = (VfwCapture *)iface;
242 TRACE("()\n");
243 return qcap_driver_pause(This->driver_info, &This->state);
246 static HRESULT WINAPI VfwCapture_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
248 VfwCapture *This = (VfwCapture *)iface;
249 TRACE("(%x%08x)\n", (ULONG)(tStart >> 32), (ULONG)tStart);
250 return qcap_driver_run(This->driver_info, &This->state);
253 static HRESULT WINAPI
254 VfwCapture_GetState( IBaseFilter * iface, DWORD dwMilliSecsTimeout,
255 FILTER_STATE *pState )
257 VfwCapture *This = (VfwCapture *)iface;
259 TRACE("(%u, %p)\n", dwMilliSecsTimeout, pState);
261 *pState = This->state;
262 return S_OK;
265 static HRESULT WINAPI
266 VfwCapture_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock)
268 TRACE("(%p)\n", pClock);
270 return S_OK;
273 static HRESULT WINAPI
274 VfwCapture_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock)
276 TRACE("(%p)\n", ppClock);
278 return S_OK;
281 /** IBaseFilter methods **/
283 static HRESULT WINAPI
284 VfwCapture_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum)
286 ENUMPINDETAILS epd;
287 VfwCapture *This = (VfwCapture *)iface;
289 TRACE("(%p)\n", ppEnum);
291 epd.cPins = 1;
292 epd.ppPins = &This->pOutputPin;
293 return IEnumPinsImpl_Construct(&epd, ppEnum);
296 static HRESULT WINAPI VfwCapture_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin)
298 FIXME("(%s, %p) - stub\n", debugstr_w(Id), ppPin);
299 return E_NOTIMPL;
302 static HRESULT WINAPI VfwCapture_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo)
304 VfwCapture *This = (VfwCapture *)iface;
306 TRACE("(%p)\n", pInfo);
308 lstrcpyW(pInfo->achName, This->filterInfo.achName);
309 pInfo->pGraph = This->filterInfo.pGraph;
311 if (pInfo->pGraph)
312 IFilterGraph_AddRef(pInfo->pGraph);
313 return S_OK;
316 static HRESULT WINAPI
317 VfwCapture_JoinFilterGraph( IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName )
319 VfwCapture *This = (VfwCapture *)iface;
321 TRACE("(%p, %s)\n", pGraph, debugstr_w(pName));
323 if (pName)
324 lstrcpyW(This->filterInfo.achName, pName);
325 else
326 *This->filterInfo.achName = 0;
327 This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */
329 return S_OK;
332 static HRESULT WINAPI
333 VfwCapture_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo)
335 FIXME("(%p) - stub\n", pVendorInfo);
336 return E_NOTIMPL;
339 static const IBaseFilterVtbl VfwCapture_Vtbl =
341 VfwCapture_QueryInterface,
342 VfwCapture_AddRef,
343 VfwCapture_Release,
344 VfwCapture_GetClassID,
345 VfwCapture_Stop,
346 VfwCapture_Pause,
347 VfwCapture_Run,
348 VfwCapture_GetState,
349 VfwCapture_SetSyncSource,
350 VfwCapture_GetSyncSource,
351 VfwCapture_EnumPins,
352 VfwCapture_FindPin,
353 VfwCapture_QueryFilterInfo,
354 VfwCapture_JoinFilterGraph,
355 VfwCapture_QueryVendorInfo
358 /* AMStreamConfig interface, we only need to implement {G,S}etFormat */
359 static HRESULT WINAPI
360 AMStreamConfig_QueryInterface( IAMStreamConfig * iface, REFIID riid, LPVOID * ppv )
362 ICOM_THIS_MULTI(VfwCapture, IAMStreamConfig_vtbl, iface);
364 TRACE("%p --> %s\n", This, debugstr_guid(riid));
366 if (IsEqualIID(riid, &IID_IUnknown) ||
367 IsEqualIID(riid, &IID_IAMStreamConfig))
369 IAMStreamConfig_AddRef(iface);
370 *ppv = iface;
371 return S_OK;
374 FIXME("No interface for iid %s\n", debugstr_guid(riid));
375 return E_NOINTERFACE;
378 static ULONG WINAPI AMStreamConfig_AddRef( IAMStreamConfig * iface )
380 ICOM_THIS_MULTI(VfwCapture, IAMStreamConfig_vtbl, iface);
382 TRACE("%p --> Forwarding to VfwCapture (%p)\n", iface, This);
383 return IUnknown_AddRef((IUnknown *)This);
386 static ULONG WINAPI AMStreamConfig_Release( IAMStreamConfig * iface )
388 ICOM_THIS_MULTI(VfwCapture, IAMStreamConfig_vtbl, iface);
390 TRACE("%p --> Forwarding to VfwCapture (%p)\n", iface, This);
391 return IUnknown_Release((IUnknown *)This);
394 static HRESULT WINAPI
395 AMStreamConfig_SetFormat(IAMStreamConfig *iface, AM_MEDIA_TYPE *pmt)
397 HRESULT hr;
398 ICOM_THIS_MULTI(VfwCapture, IAMStreamConfig_vtbl, iface);
399 IPinImpl *pin;
401 TRACE("(%p): %p->%p\n", iface, pmt, pmt->pbFormat);
403 if (This->state != State_Stopped)
405 TRACE("Returning not stopped error\n");
406 return VFW_E_NOT_STOPPED;
409 dump_AM_MEDIA_TYPE(pmt);
411 pin = (IPinImpl *)This->pOutputPin;
412 if (pin->pConnectedTo != NULL)
414 hr = IPin_QueryAccept(pin->pConnectedTo, pmt);
415 TRACE("Would accept: %d\n", hr);
416 if (hr == S_FALSE)
417 return VFW_E_INVALIDMEDIATYPE;
420 hr = qcap_driver_set_format(This->driver_info, pmt);
421 if (SUCCEEDED(hr) && This->filterInfo.pGraph && pin->pConnectedTo )
423 hr = IFilterGraph_Reconnect(This->filterInfo.pGraph, This->pOutputPin);
424 if (SUCCEEDED(hr))
425 TRACE("Reconnection completed, with new media format..\n");
427 TRACE("Returning: %d\n", hr);
428 return hr;
431 static HRESULT WINAPI
432 AMStreamConfig_GetFormat( IAMStreamConfig *iface, AM_MEDIA_TYPE **pmt )
434 ICOM_THIS_MULTI(VfwCapture, IAMStreamConfig_vtbl, iface);
436 TRACE("%p -> (%p)\n", iface, pmt);
437 return qcap_driver_get_format(This->driver_info, pmt);
440 static HRESULT WINAPI
441 AMStreamConfig_GetNumberOfCapabilities( IAMStreamConfig *iface, int *piCount,
442 int *piSize )
444 FIXME("%p: %p %p - stub, intentional\n", iface, piCount, piSize);
445 return E_NOTIMPL; /* Not implemented for this interface */
448 static HRESULT WINAPI
449 AMStreamConfig_GetStreamCaps( IAMStreamConfig *iface, int iIndex,
450 AM_MEDIA_TYPE **pmt, BYTE *pSCC )
452 FIXME("%p: %d %p %p - stub, intentional\n", iface, iIndex, pmt, pSCC);
453 return E_NOTIMPL; /* Not implemented for this interface */
456 static const IAMStreamConfigVtbl IAMStreamConfig_VTable =
458 AMStreamConfig_QueryInterface,
459 AMStreamConfig_AddRef,
460 AMStreamConfig_Release,
461 AMStreamConfig_SetFormat,
462 AMStreamConfig_GetFormat,
463 AMStreamConfig_GetNumberOfCapabilities,
464 AMStreamConfig_GetStreamCaps
467 static HRESULT WINAPI
468 AMVideoProcAmp_QueryInterface( IAMVideoProcAmp * iface, REFIID riid,
469 LPVOID * ppv )
471 if (IsEqualIID(riid, &IID_IUnknown) ||
472 IsEqualIID(riid, &IID_IAMVideoProcAmp))
474 *ppv = iface;
475 IAMVideoProcAmp_AddRef( iface );
476 return S_OK;
479 FIXME("No interface for iid %s\n", debugstr_guid(riid));
480 return E_NOINTERFACE;
483 static ULONG WINAPI AMVideoProcAmp_AddRef(IAMVideoProcAmp * iface)
485 ICOM_THIS_MULTI(VfwCapture, IAMVideoProcAmp_vtbl, iface);
487 return IUnknown_AddRef((IUnknown *)This);
490 static ULONG WINAPI AMVideoProcAmp_Release(IAMVideoProcAmp * iface)
492 ICOM_THIS_MULTI(VfwCapture, IAMVideoProcAmp_vtbl, iface);
494 return IUnknown_Release((IUnknown *)This);
497 static HRESULT WINAPI
498 AMVideoProcAmp_GetRange( IAMVideoProcAmp * iface, long Property, long *pMin,
499 long *pMax, long *pSteppingDelta, long *pDefault, long *pCapsFlags )
501 ICOM_THIS_MULTI(VfwCapture, IAMVideoProcAmp_vtbl, iface);
503 return qcap_driver_get_prop_range( This->driver_info, Property, pMin, pMax,
504 pSteppingDelta, pDefault, pCapsFlags );
507 static HRESULT WINAPI
508 AMVideoProcAmp_Set( IAMVideoProcAmp * iface, long Property, long lValue,
509 long Flags )
511 ICOM_THIS_MULTI(VfwCapture, IAMVideoProcAmp_vtbl, iface);
513 return qcap_driver_set_prop(This->driver_info, Property, lValue, Flags);
516 static HRESULT WINAPI
517 AMVideoProcAmp_Get( IAMVideoProcAmp * iface, long Property, long *lValue,
518 long *Flags )
520 ICOM_THIS_MULTI(VfwCapture, IAMVideoProcAmp_vtbl, iface);
522 return qcap_driver_get_prop(This->driver_info, Property, lValue, Flags);
525 static const IAMVideoProcAmpVtbl IAMVideoProcAmp_VTable =
527 AMVideoProcAmp_QueryInterface,
528 AMVideoProcAmp_AddRef,
529 AMVideoProcAmp_Release,
530 AMVideoProcAmp_GetRange,
531 AMVideoProcAmp_Set,
532 AMVideoProcAmp_Get,
535 static HRESULT WINAPI
536 PPB_QueryInterface( IPersistPropertyBag * iface, REFIID riid, LPVOID * ppv )
538 if (IsEqualIID(riid, &IID_IUnknown) ||
539 IsEqualIID(riid, &IID_IPersist) ||
540 IsEqualIID(riid, &IID_IPersistPropertyBag))
542 IPersistPropertyBag_AddRef(iface);
543 *ppv = iface;
544 return S_OK;
546 if (IsEqualIID(riid, &IID_IBaseFilter))
548 /* FIXME: native devenum asks for IBaseFilter, should we return it? */
549 IPersistPropertyBag_AddRef(iface);
550 *ppv = iface;
551 return S_OK;
554 FIXME("No interface for iid %s\n", debugstr_guid(riid));
555 return E_NOINTERFACE;
558 static ULONG WINAPI PPB_AddRef(IPersistPropertyBag * iface)
560 ICOM_THIS_MULTI(VfwCapture, IPersistPropertyBag_vtbl, iface);
562 TRACE("%p --> Forwarding to VfwCapture (%p)\n", iface, This);
564 return IUnknown_AddRef((IUnknown *)This);
567 static ULONG WINAPI PPB_Release(IPersistPropertyBag * iface)
569 ICOM_THIS_MULTI(VfwCapture, IPersistPropertyBag_vtbl, iface);
571 TRACE("%p --> Forwarding to VfwCapture (%p)\n", iface, This);
573 return IUnknown_Release((IUnknown *)This);
576 static HRESULT WINAPI
577 PPB_GetClassID( IPersistPropertyBag * iface, CLSID * pClassID )
579 ICOM_THIS_MULTI(VfwCapture, IPersistPropertyBag_vtbl, iface);
581 FIXME("%p - stub\n", This);
583 return E_NOTIMPL;
586 static HRESULT WINAPI PPB_InitNew(IPersistPropertyBag * iface)
588 ICOM_THIS_MULTI(VfwCapture, IPersistPropertyBag_vtbl, iface);
590 FIXME("%p - stub\n", This);
592 return E_NOTIMPL;
595 static HRESULT WINAPI
596 PPB_Load( IPersistPropertyBag * iface, IPropertyBag *pPropBag,
597 IErrorLog *pErrorLog )
599 ICOM_THIS_MULTI(VfwCapture, IPersistPropertyBag_vtbl, iface);
600 HRESULT hr;
601 VARIANT var;
602 const OLECHAR VFWIndex[] = {'V','F','W','I','n','d','e','x',0};
604 TRACE("%p/%p-> (%p, %p)\n", iface, This, pPropBag, pErrorLog);
606 V_VT(&var) = VT_I4;
607 hr = IPropertyBag_Read(pPropBag, (LPCOLESTR)VFWIndex, &var, pErrorLog);
609 if (SUCCEEDED(hr))
611 VfwPinImpl *pin;
613 This->driver_info = qcap_driver_init( This->pOutputPin,
614 var.__VARIANT_NAME_1.__VARIANT_NAME_2.__VARIANT_NAME_3.ulVal );
615 if (This->driver_info)
617 pin = (VfwPinImpl *)This->pOutputPin;
618 pin->driver_info = This->driver_info;
619 This->init = TRUE;
620 hr = S_OK;
622 else
623 hr = E_FAIL;
626 return hr;
629 static HRESULT WINAPI
630 PPB_Save( IPersistPropertyBag * iface, IPropertyBag *pPropBag,
631 BOOL fClearDirty, BOOL fSaveAllProperties )
633 ICOM_THIS_MULTI(VfwCapture, IPersistPropertyBag_vtbl, iface);
634 FIXME("%p - stub\n", This);
635 return E_NOTIMPL;
638 static const IPersistPropertyBagVtbl IPersistPropertyBag_VTable =
640 PPB_QueryInterface,
641 PPB_AddRef,
642 PPB_Release,
643 PPB_GetClassID,
644 PPB_InitNew,
645 PPB_Load,
646 PPB_Save
649 /* IKsPropertySet interface */
650 static HRESULT WINAPI
651 KSP_QueryInterface( IKsPropertySet * iface, REFIID riid, LPVOID * ppv )
653 if (IsEqualIID(riid, &IID_IUnknown) ||
654 IsEqualIID(riid, &IID_IKsPropertySet))
656 *ppv = (LPVOID)iface;
657 IKsPropertySet_AddRef( iface );
658 return S_OK;
661 FIXME("No interface for iid %s\n", debugstr_guid(riid));
662 return E_NOINTERFACE;
665 static ULONG WINAPI KSP_AddRef(IKsPropertySet * iface)
667 ICOM_THIS_MULTI(VfwPinImpl, KSP_VT, iface);
669 TRACE("%p --> Forwarding to VfwPin (%p)\n", iface, This);
671 return IUnknown_AddRef((IUnknown *)This);
674 static ULONG WINAPI KSP_Release(IKsPropertySet * iface)
676 ICOM_THIS_MULTI(VfwPinImpl, KSP_VT, iface);
678 TRACE("%p --> Forwarding to VfwPin (%p)\n", iface, This);
680 return IUnknown_Release((IUnknown *)This);
683 static HRESULT WINAPI
684 KSP_Set( IKsPropertySet * iface, REFGUID guidPropSet, DWORD dwPropID,
685 LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData,
686 DWORD cbPropData )
688 FIXME("%p: stub\n", iface);
689 return E_NOTIMPL;
692 static HRESULT WINAPI
693 KSP_Get( IKsPropertySet * iface, REFGUID guidPropSet, DWORD dwPropID,
694 LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData,
695 DWORD cbPropData, DWORD *pcbReturned )
697 LPGUID pGuid;
699 TRACE("()\n");
701 if (!IsEqualIID(guidPropSet, &AMPROPSETID_Pin))
702 return E_PROP_SET_UNSUPPORTED;
703 if (pPropData == NULL && pcbReturned == NULL)
704 return E_POINTER;
705 if (pcbReturned)
706 *pcbReturned = sizeof(GUID);
707 if (pPropData == NULL)
708 return S_OK;
709 if (cbPropData < sizeof(GUID))
710 return E_UNEXPECTED;
711 pGuid = pPropData;
712 *pGuid = PIN_CATEGORY_PREVIEW;
713 FIXME("() Not adding a pin with PIN_CATEGORY_CAPTURE\n");
714 return S_OK;
717 static HRESULT WINAPI
718 KSP_QuerySupported( IKsPropertySet * iface, REFGUID guidPropSet,
719 DWORD dwPropID, DWORD *pTypeSupport )
721 FIXME("%p: stub\n", iface);
722 return E_NOTIMPL;
725 static const IKsPropertySetVtbl KSP_VTable =
727 KSP_QueryInterface,
728 KSP_AddRef,
729 KSP_Release,
730 KSP_Set,
731 KSP_Get,
732 KSP_QuerySupported
735 static HRESULT
736 VfwPin_Construct( IBaseFilter * pBaseFilter, LPCRITICAL_SECTION pCritSec,
737 IPin ** ppPin )
739 static const WCHAR wszOutputPinName[] = { 'O','u','t','p','u','t',0 };
740 ALLOCATOR_PROPERTIES ap;
741 VfwPinImpl * pPinImpl;
742 PIN_INFO piOutput;
743 HRESULT hr;
745 pPinImpl = CoTaskMemAlloc( sizeof(*pPinImpl) );
746 if (!pPinImpl)
747 return E_OUTOFMEMORY;
749 /* What we put here doesn't matter, the
750 driver function should override it then commit */
751 ap.cBuffers = 3;
752 ap.cbBuffer = 230400;
753 ap.cbAlign = 1;
754 ap.cbPrefix = 0;
756 piOutput.dir = PINDIR_OUTPUT;
757 piOutput.pFilter = pBaseFilter;
758 lstrcpyW(piOutput.achName, wszOutputPinName);
759 ObjectRefCount(TRUE);
761 hr = OutputPin_Init(&piOutput, &ap, pBaseFilter, NULL, pCritSec, &pPinImpl->pin);
762 if (SUCCEEDED(hr))
764 pPinImpl->KSP_VT = &KSP_VTable;
765 pPinImpl->pin.pin.lpVtbl = &VfwPin_Vtbl;
766 *ppPin = (IPin *)(&pPinImpl->pin.pin.lpVtbl);
767 return S_OK;
769 return E_FAIL;
772 static HRESULT WINAPI VfwPin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv)
774 VfwPinImpl *This = (VfwPinImpl *)iface;
776 TRACE("%s %p\n", debugstr_guid(riid), ppv);
778 *ppv = NULL;
779 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IPin))
780 *ppv = (LPVOID)This;
781 else if (IsEqualIID(riid, &IID_IKsPropertySet))
782 *ppv = (LPVOID)&(This->KSP_VT);
784 if (*ppv)
786 IUnknown_AddRef((IUnknown *)(*ppv));
787 return S_OK;
790 FIXME("No interface for %s!\n", debugstr_guid(riid));
791 return E_NOINTERFACE;
794 static ULONG WINAPI VfwPin_AddRef(IPin * iface)
796 VfwPinImpl *This = (VfwPinImpl *)iface;
797 ULONG refCount = InterlockedIncrement(&This->pin.pin.refCount);
799 TRACE("() -> new refcount: %u\n", refCount);
801 return refCount;
804 static ULONG WINAPI
805 VfwPin_Release(IPin * iface)
807 VfwPinImpl *This = (VfwPinImpl *)iface;
808 ULONG refCount = InterlockedDecrement(&This->pin.pin.refCount);
810 TRACE("() -> new refcount: %u\n", refCount);
812 if (!refCount)
814 CoTaskMemFree(This);
815 ObjectRefCount(FALSE);
817 return refCount;
820 static HRESULT WINAPI
821 VfwPin_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum)
823 ENUMMEDIADETAILS emd;
824 AM_MEDIA_TYPE *pmt;
825 HRESULT hr;
827 VfwPinImpl *This = (VfwPinImpl *)iface;
828 emd.cMediaTypes = 1;
829 hr = qcap_driver_get_format(This->driver_info, &pmt);
830 emd.pMediaTypes = pmt;
831 if (SUCCEEDED(hr))
832 hr = IEnumMediaTypesImpl_Construct(&emd, ppEnum);
833 TRACE("%p -- %x\n", This, hr);
834 DeleteMediaType(pmt);
835 return hr;
838 static HRESULT WINAPI
839 VfwPin_QueryInternalConnections(IPin * iface, IPin ** apPin, ULONG * cPin)
841 TRACE("(%p)->(%p, %p)\n", iface, apPin, cPin);
842 return E_NOTIMPL;
845 static HRESULT WINAPI VfwPin_EndOfStream(IPin * iface)
847 TRACE("()\n");
848 return E_UNEXPECTED;
851 static HRESULT WINAPI VfwPin_BeginFlush(IPin * iface)
853 TRACE("(%p)->()\n", iface);
854 return E_UNEXPECTED;
857 static HRESULT WINAPI VfwPin_EndFlush(IPin * iface)
859 TRACE("(%p)->()\n", iface);
860 return E_UNEXPECTED;
863 static HRESULT WINAPI
864 VfwPin_NewSegment(IPin * iface, REFERENCE_TIME tStart,
865 REFERENCE_TIME tStop, double dRate)
867 TRACE("(%p)->(%s, %s, %e)\n", iface, wine_dbgstr_longlong(tStart),
868 wine_dbgstr_longlong(tStop), dRate);
869 return E_UNEXPECTED;
872 static const IPinVtbl VfwPin_Vtbl =
874 VfwPin_QueryInterface,
875 VfwPin_AddRef,
876 VfwPin_Release,
877 OutputPin_Connect,
878 OutputPin_ReceiveConnection,
879 OutputPin_Disconnect,
880 IPinImpl_ConnectedTo,
881 IPinImpl_ConnectionMediaType,
882 IPinImpl_QueryPinInfo,
883 IPinImpl_QueryDirection,
884 IPinImpl_QueryId,
885 IPinImpl_QueryAccept,
886 VfwPin_EnumMediaTypes,
887 VfwPin_QueryInternalConnections,
888 VfwPin_EndOfStream,
889 VfwPin_BeginFlush,
890 VfwPin_EndFlush,
891 VfwPin_NewSegment