push 3f945e9775023a88a9fe5158a41ae6d84ee66613
[wine/hacks.git] / dlls / qcap / vfwcapture.c
blobb461054fcd9b23d8c3bc37fdfb9af1b683e4f351
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 "vfwmsgs.h"
42 #include "amvideo.h"
43 #include "strmif.h"
44 #include "ddraw.h"
45 #include "ocidl.h"
46 #include "oleauto.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(qcap);
50 #define ICOM_THIS_MULTI(impl,field,iface) \
51 impl* const This=(impl*)((char*)(iface) - offsetof(impl,field))
53 static const IBaseFilterVtbl VfwCapture_Vtbl;
54 static const IAMStreamConfigVtbl IAMStreamConfig_VTable;
55 static const IAMVideoProcAmpVtbl IAMVideoProcAmp_VTable;
56 static const IPersistPropertyBagVtbl IPersistPropertyBag_VTable;
57 static const IPinVtbl VfwPin_Vtbl;
59 static HRESULT VfwPin_Construct( IBaseFilter *, LPCRITICAL_SECTION, IPin ** );
61 typedef struct VfwCapture
63 const IBaseFilterVtbl * lpVtbl;
64 const IAMStreamConfigVtbl * IAMStreamConfig_vtbl;
65 const IAMVideoProcAmpVtbl * IAMVideoProcAmp_vtbl;
66 const IPersistPropertyBagVtbl * IPersistPropertyBag_vtbl;
68 BOOL init;
69 Capture *driver_info;
70 LONG refCount;
71 FILTER_INFO filterInfo;
72 FILTER_STATE state;
73 CRITICAL_SECTION csFilter;
75 IPin * pOutputPin;
76 } VfwCapture;
78 /* VfwPin implementation */
79 typedef struct VfwPinImpl
81 OutputPin pin;
82 Capture *driver_info;
83 const IKsPropertySetVtbl * KSP_VT;
84 } VfwPinImpl;
87 IUnknown * WINAPI QCAP_createVFWCaptureFilter(IUnknown *pUnkOuter, HRESULT *phr)
89 VfwCapture *pVfwCapture;
90 HRESULT hr;
92 TRACE("%p - %p\n", pUnkOuter, phr);
94 *phr = CLASS_E_NOAGGREGATION;
95 if (pUnkOuter)
96 return NULL;
97 *phr = E_OUTOFMEMORY;
99 pVfwCapture = CoTaskMemAlloc( sizeof(VfwCapture) );
101 if (!pVfwCapture)
102 return NULL;
104 pVfwCapture->lpVtbl = &VfwCapture_Vtbl;
105 pVfwCapture->IAMStreamConfig_vtbl = &IAMStreamConfig_VTable;
106 pVfwCapture->IAMVideoProcAmp_vtbl = &IAMVideoProcAmp_VTable;
107 pVfwCapture->IPersistPropertyBag_vtbl = &IPersistPropertyBag_VTable;
108 pVfwCapture->refCount = 1;
109 pVfwCapture->filterInfo.achName[0] = '\0';
110 pVfwCapture->filterInfo.pGraph = NULL;
111 pVfwCapture->state = State_Stopped;
112 pVfwCapture->init = FALSE;
113 InitializeCriticalSection(&pVfwCapture->csFilter);
114 pVfwCapture->csFilter.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": VfwCapture.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 This->csFilter.DebugInfo->Spare[0] = 0;
212 DeleteCriticalSection(&This->csFilter);
213 This->lpVtbl = NULL;
214 CoTaskMemFree(This);
215 ObjectRefCount(FALSE);
217 return refCount;
220 /** IPersist methods **/
222 static HRESULT WINAPI VfwCapture_GetClassID(IBaseFilter * iface, CLSID * pClsid)
224 TRACE("(%p)\n", pClsid);
225 *pClsid = CLSID_VfwCapture;
226 return S_OK;
229 /** IMediaFilter methods **/
231 static HRESULT WINAPI VfwCapture_Stop(IBaseFilter * iface)
233 VfwCapture *This = (VfwCapture *)iface;
235 TRACE("()\n");
236 return qcap_driver_stop(This->driver_info, &This->state);
239 static HRESULT WINAPI VfwCapture_Pause(IBaseFilter * iface)
241 VfwCapture *This = (VfwCapture *)iface;
243 TRACE("()\n");
244 return qcap_driver_pause(This->driver_info, &This->state);
247 static HRESULT WINAPI VfwCapture_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
249 VfwCapture *This = (VfwCapture *)iface;
250 TRACE("(%x%08x)\n", (ULONG)(tStart >> 32), (ULONG)tStart);
251 return qcap_driver_run(This->driver_info, &This->state);
254 static HRESULT WINAPI
255 VfwCapture_GetState( IBaseFilter * iface, DWORD dwMilliSecsTimeout,
256 FILTER_STATE *pState )
258 VfwCapture *This = (VfwCapture *)iface;
260 TRACE("(%u, %p)\n", dwMilliSecsTimeout, pState);
262 *pState = This->state;
263 return S_OK;
266 static HRESULT WINAPI
267 VfwCapture_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock)
269 TRACE("(%p)\n", pClock);
271 return S_OK;
274 static HRESULT WINAPI
275 VfwCapture_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock)
277 TRACE("(%p)\n", ppClock);
279 return S_OK;
282 /** IBaseFilter methods **/
284 static HRESULT WINAPI
285 VfwCapture_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum)
287 ENUMPINDETAILS epd;
288 VfwCapture *This = (VfwCapture *)iface;
290 TRACE("(%p)\n", ppEnum);
292 epd.cPins = 1;
293 epd.ppPins = &This->pOutputPin;
294 return IEnumPinsImpl_Construct(&epd, ppEnum);
297 static HRESULT WINAPI VfwCapture_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin)
299 FIXME("(%s, %p) - stub\n", debugstr_w(Id), ppPin);
300 return E_NOTIMPL;
303 static HRESULT WINAPI VfwCapture_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo)
305 VfwCapture *This = (VfwCapture *)iface;
307 TRACE("(%p)\n", pInfo);
309 lstrcpyW(pInfo->achName, This->filterInfo.achName);
310 pInfo->pGraph = This->filterInfo.pGraph;
312 if (pInfo->pGraph)
313 IFilterGraph_AddRef(pInfo->pGraph);
314 return S_OK;
317 static HRESULT WINAPI
318 VfwCapture_JoinFilterGraph( IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName )
320 VfwCapture *This = (VfwCapture *)iface;
322 TRACE("(%p, %s)\n", pGraph, debugstr_w(pName));
324 if (pName)
325 lstrcpyW(This->filterInfo.achName, pName);
326 else
327 *This->filterInfo.achName = 0;
328 This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */
330 return S_OK;
333 static HRESULT WINAPI
334 VfwCapture_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo)
336 FIXME("(%p) - stub\n", pVendorInfo);
337 return E_NOTIMPL;
340 static const IBaseFilterVtbl VfwCapture_Vtbl =
342 VfwCapture_QueryInterface,
343 VfwCapture_AddRef,
344 VfwCapture_Release,
345 VfwCapture_GetClassID,
346 VfwCapture_Stop,
347 VfwCapture_Pause,
348 VfwCapture_Run,
349 VfwCapture_GetState,
350 VfwCapture_SetSyncSource,
351 VfwCapture_GetSyncSource,
352 VfwCapture_EnumPins,
353 VfwCapture_FindPin,
354 VfwCapture_QueryFilterInfo,
355 VfwCapture_JoinFilterGraph,
356 VfwCapture_QueryVendorInfo
359 /* AMStreamConfig interface, we only need to implement {G,S}etFormat */
360 static HRESULT WINAPI
361 AMStreamConfig_QueryInterface( IAMStreamConfig * iface, REFIID riid, LPVOID * ppv )
363 ICOM_THIS_MULTI(VfwCapture, IAMStreamConfig_vtbl, iface);
365 TRACE("%p --> %s\n", This, debugstr_guid(riid));
367 if (IsEqualIID(riid, &IID_IUnknown) ||
368 IsEqualIID(riid, &IID_IAMStreamConfig))
370 IAMStreamConfig_AddRef(iface);
371 *ppv = iface;
372 return S_OK;
375 FIXME("No interface for iid %s\n", debugstr_guid(riid));
376 return E_NOINTERFACE;
379 static ULONG WINAPI AMStreamConfig_AddRef( IAMStreamConfig * iface )
381 ICOM_THIS_MULTI(VfwCapture, IAMStreamConfig_vtbl, iface);
383 TRACE("%p --> Forwarding to VfwCapture (%p)\n", iface, This);
384 return IUnknown_AddRef((IUnknown *)This);
387 static ULONG WINAPI AMStreamConfig_Release( IAMStreamConfig * iface )
389 ICOM_THIS_MULTI(VfwCapture, IAMStreamConfig_vtbl, iface);
391 TRACE("%p --> Forwarding to VfwCapture (%p)\n", iface, This);
392 return IUnknown_Release((IUnknown *)This);
395 static HRESULT WINAPI
396 AMStreamConfig_SetFormat(IAMStreamConfig *iface, AM_MEDIA_TYPE *pmt)
398 HRESULT hr;
399 ICOM_THIS_MULTI(VfwCapture, IAMStreamConfig_vtbl, iface);
400 IPinImpl *pin;
402 TRACE("(%p): %p->%p\n", iface, pmt, pmt->pbFormat);
404 if (This->state != State_Stopped)
406 TRACE("Returning not stopped error\n");
407 return VFW_E_NOT_STOPPED;
410 dump_AM_MEDIA_TYPE(pmt);
412 pin = (IPinImpl *)This->pOutputPin;
413 if (pin->pConnectedTo != NULL)
415 hr = IPin_QueryAccept(pin->pConnectedTo, pmt);
416 TRACE("Would accept: %d\n", hr);
417 if (hr == S_FALSE)
418 return VFW_E_INVALIDMEDIATYPE;
421 hr = qcap_driver_set_format(This->driver_info, pmt);
422 if (SUCCEEDED(hr) && This->filterInfo.pGraph && pin->pConnectedTo )
424 hr = IFilterGraph_Reconnect(This->filterInfo.pGraph, This->pOutputPin);
425 if (SUCCEEDED(hr))
426 TRACE("Reconnection completed, with new media format..\n");
428 TRACE("Returning: %d\n", hr);
429 return hr;
432 static HRESULT WINAPI
433 AMStreamConfig_GetFormat( IAMStreamConfig *iface, AM_MEDIA_TYPE **pmt )
435 ICOM_THIS_MULTI(VfwCapture, IAMStreamConfig_vtbl, iface);
437 TRACE("%p -> (%p)\n", iface, pmt);
438 return qcap_driver_get_format(This->driver_info, pmt);
441 static HRESULT WINAPI
442 AMStreamConfig_GetNumberOfCapabilities( IAMStreamConfig *iface, int *piCount,
443 int *piSize )
445 FIXME("%p: %p %p - stub, intentional\n", iface, piCount, piSize);
446 return E_NOTIMPL; /* Not implemented for this interface */
449 static HRESULT WINAPI
450 AMStreamConfig_GetStreamCaps( IAMStreamConfig *iface, int iIndex,
451 AM_MEDIA_TYPE **pmt, BYTE *pSCC )
453 FIXME("%p: %d %p %p - stub, intentional\n", iface, iIndex, pmt, pSCC);
454 return E_NOTIMPL; /* Not implemented for this interface */
457 static const IAMStreamConfigVtbl IAMStreamConfig_VTable =
459 AMStreamConfig_QueryInterface,
460 AMStreamConfig_AddRef,
461 AMStreamConfig_Release,
462 AMStreamConfig_SetFormat,
463 AMStreamConfig_GetFormat,
464 AMStreamConfig_GetNumberOfCapabilities,
465 AMStreamConfig_GetStreamCaps
468 static HRESULT WINAPI
469 AMVideoProcAmp_QueryInterface( IAMVideoProcAmp * iface, REFIID riid,
470 LPVOID * ppv )
472 if (IsEqualIID(riid, &IID_IUnknown) ||
473 IsEqualIID(riid, &IID_IAMVideoProcAmp))
475 *ppv = iface;
476 IAMVideoProcAmp_AddRef( iface );
477 return S_OK;
480 FIXME("No interface for iid %s\n", debugstr_guid(riid));
481 return E_NOINTERFACE;
484 static ULONG WINAPI AMVideoProcAmp_AddRef(IAMVideoProcAmp * iface)
486 ICOM_THIS_MULTI(VfwCapture, IAMVideoProcAmp_vtbl, iface);
488 return IUnknown_AddRef((IUnknown *)This);
491 static ULONG WINAPI AMVideoProcAmp_Release(IAMVideoProcAmp * iface)
493 ICOM_THIS_MULTI(VfwCapture, IAMVideoProcAmp_vtbl, iface);
495 return IUnknown_Release((IUnknown *)This);
498 static HRESULT WINAPI
499 AMVideoProcAmp_GetRange( IAMVideoProcAmp * iface, long Property, long *pMin,
500 long *pMax, long *pSteppingDelta, long *pDefault, long *pCapsFlags )
502 ICOM_THIS_MULTI(VfwCapture, IAMVideoProcAmp_vtbl, iface);
504 return qcap_driver_get_prop_range( This->driver_info, Property, pMin, pMax,
505 pSteppingDelta, pDefault, pCapsFlags );
508 static HRESULT WINAPI
509 AMVideoProcAmp_Set( IAMVideoProcAmp * iface, long Property, long lValue,
510 long Flags )
512 ICOM_THIS_MULTI(VfwCapture, IAMVideoProcAmp_vtbl, iface);
514 return qcap_driver_set_prop(This->driver_info, Property, lValue, Flags);
517 static HRESULT WINAPI
518 AMVideoProcAmp_Get( IAMVideoProcAmp * iface, long Property, long *lValue,
519 long *Flags )
521 ICOM_THIS_MULTI(VfwCapture, IAMVideoProcAmp_vtbl, iface);
523 return qcap_driver_get_prop(This->driver_info, Property, lValue, Flags);
526 static const IAMVideoProcAmpVtbl IAMVideoProcAmp_VTable =
528 AMVideoProcAmp_QueryInterface,
529 AMVideoProcAmp_AddRef,
530 AMVideoProcAmp_Release,
531 AMVideoProcAmp_GetRange,
532 AMVideoProcAmp_Set,
533 AMVideoProcAmp_Get,
536 static HRESULT WINAPI
537 PPB_QueryInterface( IPersistPropertyBag * iface, REFIID riid, LPVOID * ppv )
539 if (IsEqualIID(riid, &IID_IUnknown) ||
540 IsEqualIID(riid, &IID_IPersist) ||
541 IsEqualIID(riid, &IID_IPersistPropertyBag))
543 IPersistPropertyBag_AddRef(iface);
544 *ppv = iface;
545 return S_OK;
547 if (IsEqualIID(riid, &IID_IBaseFilter))
549 /* FIXME: native devenum asks for IBaseFilter, should we return it? */
550 IPersistPropertyBag_AddRef(iface);
551 *ppv = iface;
552 return S_OK;
555 FIXME("No interface for iid %s\n", debugstr_guid(riid));
556 return E_NOINTERFACE;
559 static ULONG WINAPI PPB_AddRef(IPersistPropertyBag * iface)
561 ICOM_THIS_MULTI(VfwCapture, IPersistPropertyBag_vtbl, iface);
563 TRACE("%p --> Forwarding to VfwCapture (%p)\n", iface, This);
565 return IUnknown_AddRef((IUnknown *)This);
568 static ULONG WINAPI PPB_Release(IPersistPropertyBag * iface)
570 ICOM_THIS_MULTI(VfwCapture, IPersistPropertyBag_vtbl, iface);
572 TRACE("%p --> Forwarding to VfwCapture (%p)\n", iface, This);
574 return IUnknown_Release((IUnknown *)This);
577 static HRESULT WINAPI
578 PPB_GetClassID( IPersistPropertyBag * iface, CLSID * pClassID )
580 ICOM_THIS_MULTI(VfwCapture, IPersistPropertyBag_vtbl, iface);
582 FIXME("%p - stub\n", This);
584 return E_NOTIMPL;
587 static HRESULT WINAPI PPB_InitNew(IPersistPropertyBag * iface)
589 ICOM_THIS_MULTI(VfwCapture, IPersistPropertyBag_vtbl, iface);
591 FIXME("%p - stub\n", This);
593 return E_NOTIMPL;
596 static HRESULT WINAPI
597 PPB_Load( IPersistPropertyBag * iface, IPropertyBag *pPropBag,
598 IErrorLog *pErrorLog )
600 ICOM_THIS_MULTI(VfwCapture, IPersistPropertyBag_vtbl, iface);
601 HRESULT hr;
602 VARIANT var;
603 const OLECHAR VFWIndex[] = {'V','F','W','I','n','d','e','x',0};
605 TRACE("%p/%p-> (%p, %p)\n", iface, This, pPropBag, pErrorLog);
607 V_VT(&var) = VT_I4;
608 hr = IPropertyBag_Read(pPropBag, (LPCOLESTR)VFWIndex, &var, pErrorLog);
610 if (SUCCEEDED(hr))
612 VfwPinImpl *pin;
614 This->driver_info = qcap_driver_init( This->pOutputPin,
615 var.__VARIANT_NAME_1.__VARIANT_NAME_2.__VARIANT_NAME_3.ulVal );
616 if (This->driver_info)
618 pin = (VfwPinImpl *)This->pOutputPin;
619 pin->driver_info = This->driver_info;
620 This->init = TRUE;
621 hr = S_OK;
623 else
624 hr = E_FAIL;
627 return hr;
630 static HRESULT WINAPI
631 PPB_Save( IPersistPropertyBag * iface, IPropertyBag *pPropBag,
632 BOOL fClearDirty, BOOL fSaveAllProperties )
634 ICOM_THIS_MULTI(VfwCapture, IPersistPropertyBag_vtbl, iface);
635 FIXME("%p - stub\n", This);
636 return E_NOTIMPL;
639 static const IPersistPropertyBagVtbl IPersistPropertyBag_VTable =
641 PPB_QueryInterface,
642 PPB_AddRef,
643 PPB_Release,
644 PPB_GetClassID,
645 PPB_InitNew,
646 PPB_Load,
647 PPB_Save
650 /* IKsPropertySet interface */
651 static HRESULT WINAPI
652 KSP_QueryInterface( IKsPropertySet * iface, REFIID riid, LPVOID * ppv )
654 if (IsEqualIID(riid, &IID_IUnknown) ||
655 IsEqualIID(riid, &IID_IKsPropertySet))
657 *ppv = (LPVOID)iface;
658 IKsPropertySet_AddRef( iface );
659 return S_OK;
662 FIXME("No interface for iid %s\n", debugstr_guid(riid));
663 return E_NOINTERFACE;
666 static ULONG WINAPI KSP_AddRef(IKsPropertySet * iface)
668 ICOM_THIS_MULTI(VfwPinImpl, KSP_VT, iface);
670 TRACE("%p --> Forwarding to VfwPin (%p)\n", iface, This);
672 return IUnknown_AddRef((IUnknown *)This);
675 static ULONG WINAPI KSP_Release(IKsPropertySet * iface)
677 ICOM_THIS_MULTI(VfwPinImpl, KSP_VT, iface);
679 TRACE("%p --> Forwarding to VfwPin (%p)\n", iface, This);
681 return IUnknown_Release((IUnknown *)This);
684 static HRESULT WINAPI
685 KSP_Set( IKsPropertySet * iface, REFGUID guidPropSet, DWORD dwPropID,
686 LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData,
687 DWORD cbPropData )
689 FIXME("%p: stub\n", iface);
690 return E_NOTIMPL;
693 static HRESULT WINAPI
694 KSP_Get( IKsPropertySet * iface, REFGUID guidPropSet, DWORD dwPropID,
695 LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData,
696 DWORD cbPropData, DWORD *pcbReturned )
698 LPGUID pGuid;
700 TRACE("()\n");
702 if (!IsEqualIID(guidPropSet, &AMPROPSETID_Pin))
703 return E_PROP_SET_UNSUPPORTED;
704 if (pPropData == NULL && pcbReturned == NULL)
705 return E_POINTER;
706 if (pcbReturned)
707 *pcbReturned = sizeof(GUID);
708 if (pPropData == NULL)
709 return S_OK;
710 if (cbPropData < sizeof(GUID))
711 return E_UNEXPECTED;
712 pGuid = pPropData;
713 *pGuid = PIN_CATEGORY_PREVIEW;
714 FIXME("() Not adding a pin with PIN_CATEGORY_CAPTURE\n");
715 return S_OK;
718 static HRESULT WINAPI
719 KSP_QuerySupported( IKsPropertySet * iface, REFGUID guidPropSet,
720 DWORD dwPropID, DWORD *pTypeSupport )
722 FIXME("%p: stub\n", iface);
723 return E_NOTIMPL;
726 static const IKsPropertySetVtbl KSP_VTable =
728 KSP_QueryInterface,
729 KSP_AddRef,
730 KSP_Release,
731 KSP_Set,
732 KSP_Get,
733 KSP_QuerySupported
736 static HRESULT
737 VfwPin_Construct( IBaseFilter * pBaseFilter, LPCRITICAL_SECTION pCritSec,
738 IPin ** ppPin )
740 static const WCHAR wszOutputPinName[] = { 'O','u','t','p','u','t',0 };
741 ALLOCATOR_PROPERTIES ap;
742 VfwPinImpl * pPinImpl;
743 PIN_INFO piOutput;
744 HRESULT hr;
746 pPinImpl = CoTaskMemAlloc( sizeof(*pPinImpl) );
747 if (!pPinImpl)
748 return E_OUTOFMEMORY;
750 /* What we put here doesn't matter, the
751 driver function should override it then commit */
752 ap.cBuffers = 3;
753 ap.cbBuffer = 230400;
754 ap.cbAlign = 1;
755 ap.cbPrefix = 0;
757 piOutput.dir = PINDIR_OUTPUT;
758 piOutput.pFilter = pBaseFilter;
759 lstrcpyW(piOutput.achName, wszOutputPinName);
760 ObjectRefCount(TRUE);
762 hr = OutputPin_Init(&piOutput, &ap, pBaseFilter, NULL, pCritSec, &pPinImpl->pin);
763 if (SUCCEEDED(hr))
765 pPinImpl->KSP_VT = &KSP_VTable;
766 pPinImpl->pin.pin.lpVtbl = &VfwPin_Vtbl;
767 *ppPin = (IPin *)(&pPinImpl->pin.pin.lpVtbl);
768 return S_OK;
770 return E_FAIL;
773 static HRESULT WINAPI VfwPin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv)
775 VfwPinImpl *This = (VfwPinImpl *)iface;
777 TRACE("%s %p\n", debugstr_guid(riid), ppv);
779 *ppv = NULL;
780 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IPin))
781 *ppv = (LPVOID)This;
782 else if (IsEqualIID(riid, &IID_IKsPropertySet))
783 *ppv = (LPVOID)&(This->KSP_VT);
785 if (*ppv)
787 IUnknown_AddRef((IUnknown *)(*ppv));
788 return S_OK;
791 FIXME("No interface for %s!\n", debugstr_guid(riid));
792 return E_NOINTERFACE;
795 static ULONG WINAPI VfwPin_AddRef(IPin * iface)
797 VfwPinImpl *This = (VfwPinImpl *)iface;
798 ULONG refCount = InterlockedIncrement(&This->pin.pin.refCount);
800 TRACE("() -> new refcount: %u\n", refCount);
802 return refCount;
805 static ULONG WINAPI
806 VfwPin_Release(IPin * iface)
808 VfwPinImpl *This = (VfwPinImpl *)iface;
809 ULONG refCount = InterlockedDecrement(&This->pin.pin.refCount);
811 TRACE("() -> new refcount: %u\n", refCount);
813 if (!refCount)
815 CoTaskMemFree(This);
816 ObjectRefCount(FALSE);
818 return refCount;
821 static HRESULT WINAPI
822 VfwPin_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum)
824 ENUMMEDIADETAILS emd;
825 AM_MEDIA_TYPE *pmt;
826 HRESULT hr;
828 VfwPinImpl *This = (VfwPinImpl *)iface;
829 emd.cMediaTypes = 1;
830 hr = qcap_driver_get_format(This->driver_info, &pmt);
831 emd.pMediaTypes = pmt;
832 if (SUCCEEDED(hr))
833 hr = IEnumMediaTypesImpl_Construct(&emd, ppEnum);
834 TRACE("%p -- %x\n", This, hr);
835 DeleteMediaType(pmt);
836 return hr;
839 static HRESULT WINAPI
840 VfwPin_QueryInternalConnections(IPin * iface, IPin ** apPin, ULONG * cPin)
842 TRACE("(%p)->(%p, %p)\n", iface, apPin, cPin);
843 return E_NOTIMPL;
846 static HRESULT WINAPI VfwPin_EndOfStream(IPin * iface)
848 TRACE("()\n");
849 return E_UNEXPECTED;
852 static HRESULT WINAPI VfwPin_BeginFlush(IPin * iface)
854 TRACE("(%p)->()\n", iface);
855 return E_UNEXPECTED;
858 static HRESULT WINAPI VfwPin_EndFlush(IPin * iface)
860 TRACE("(%p)->()\n", iface);
861 return E_UNEXPECTED;
864 static HRESULT WINAPI
865 VfwPin_NewSegment(IPin * iface, REFERENCE_TIME tStart,
866 REFERENCE_TIME tStop, double dRate)
868 TRACE("(%p)->(%s, %s, %e)\n", iface, wine_dbgstr_longlong(tStart),
869 wine_dbgstr_longlong(tStop), dRate);
870 return E_UNEXPECTED;
873 static const IPinVtbl VfwPin_Vtbl =
875 VfwPin_QueryInterface,
876 VfwPin_AddRef,
877 VfwPin_Release,
878 OutputPin_Connect,
879 OutputPin_ReceiveConnection,
880 OutputPin_Disconnect,
881 IPinImpl_ConnectedTo,
882 IPinImpl_ConnectionMediaType,
883 IPinImpl_QueryPinInfo,
884 IPinImpl_QueryDirection,
885 IPinImpl_QueryId,
886 IPinImpl_QueryAccept,
887 VfwPin_EnumMediaTypes,
888 VfwPin_QueryInternalConnections,
889 VfwPin_EndOfStream,
890 VfwPin_BeginFlush,
891 VfwPin_EndFlush,
892 VfwPin_NewSegment