diff --git a/dlls/qcap/Makefile.in b/dlls/qcap/Makefile.in index aa778f4443a..71a785bc969 100644 --- a/dlls/qcap/Makefile.in +++ b/dlls/qcap/Makefile.in @@ -3,6 +3,7 @@ IMPORTS = strmiids strmbase uuid ole32 oleaut32 gdi32 advapi32 DELAYIMPORTS = msvfw32 C_SRCS = \ + audiorecord.c \ avico.c \ avimux.c \ capturegraph.c \ diff --git a/dlls/qcap/audiorecord.c b/dlls/qcap/audiorecord.c new file mode 100644 index 00000000000..75022883f13 --- /dev/null +++ b/dlls/qcap/audiorecord.c @@ -0,0 +1,302 @@ +/* Implementation of the Audio Capture Filter (CLSID_AudioRecord) + * + * Copyright 2015 Damjan Jovanovic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include + +#define COBJMACROS + +#include "windef.h" +#include "winbase.h" +#include "wtypes.h" +#include "wingdi.h" +#include "winuser.h" +#include "dshow.h" + +#include "qcap_main.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(qcap); + +typedef struct { + IUnknown IUnknown_iface; + IUnknown *outerUnknown; + BaseFilter filter; + IPersistPropertyBag IPersistPropertyBag_iface; + BaseOutputPin *output; +} AudioRecord; + +static inline AudioRecord *impl_from_IUnknown(IUnknown *iface) +{ + return CONTAINING_RECORD(iface, AudioRecord, IUnknown_iface); +} + +static inline AudioRecord *impl_from_BaseFilter(BaseFilter *filter) +{ + return CONTAINING_RECORD(filter, AudioRecord, filter); +} + +static inline AudioRecord *impl_from_IBaseFilter(IBaseFilter *iface) +{ + BaseFilter *filter = CONTAINING_RECORD(iface, BaseFilter, IBaseFilter_iface); + return impl_from_BaseFilter(filter); +} + +static inline AudioRecord *impl_from_IPersistPropertyBag(IPersistPropertyBag *iface) +{ + return CONTAINING_RECORD(iface, AudioRecord, IPersistPropertyBag_iface); +} + +static HRESULT WINAPI Unknown_QueryInterface(IUnknown *iface, REFIID riid, LPVOID *ppv) +{ + AudioRecord *This = impl_from_IUnknown(iface); + if (IsEqualIID(riid, &IID_IUnknown)) { + TRACE("(%p)->(IID_IUnknown, %p)\n", This, ppv); + *ppv = &This->filter.IBaseFilter_iface; + } else if (IsEqualIID(riid, &IID_IPersist)) { + TRACE("(%p)->(IID_IPersist, %p)\n", This, ppv); + *ppv = &This->filter.IBaseFilter_iface; + } else if (IsEqualIID(riid, &IID_IMediaFilter)) { + TRACE("(%p)->(IID_IMediaFilter, %p)\n", This, ppv); + *ppv = &This->filter.IBaseFilter_iface; + } else if (IsEqualIID(riid, &IID_IBaseFilter)) { + TRACE("(%p)->(IID_IBaseFilter, %p)\n", This, ppv); + *ppv = &This->filter.IBaseFilter_iface; + } else if (IsEqualIID(riid, &IID_IPersistPropertyBag)) { + TRACE("(%p)->(IID_IPersistPropertyBag, %p)\n", This, ppv); + *ppv = &This->IPersistPropertyBag_iface; + } else { + FIXME("(%p): no interface for %s\n", This, debugstr_guid(riid)); + *ppv = NULL; + return E_NOINTERFACE; + } + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; +} + +static ULONG WINAPI Unknown_AddRef(IUnknown *iface) +{ + AudioRecord *This = impl_from_IUnknown(iface); + return BaseFilterImpl_AddRef(&This->filter.IBaseFilter_iface); +} + +static ULONG WINAPI Unknown_Release(IUnknown *iface) +{ + AudioRecord *This = impl_from_IUnknown(iface); + ULONG ref = BaseFilterImpl_Release(&This->filter.IBaseFilter_iface); + TRACE("(%p/%p)->() ref=%d\n", iface, This, ref); + if (!ref) { + CoTaskMemFree(This); + } + return ref; +} + +static const IUnknownVtbl UnknownVtbl = { + Unknown_QueryInterface, + Unknown_AddRef, + Unknown_Release +}; + +static HRESULT WINAPI AudioRecord_QueryInterface(IBaseFilter *iface, REFIID riid, void **ppv) +{ + AudioRecord *This = impl_from_IBaseFilter(iface); + return IUnknown_QueryInterface(This->outerUnknown, riid, ppv); +} + +static ULONG WINAPI AudioRecord_AddRef(IBaseFilter *iface) +{ + AudioRecord *This = impl_from_IBaseFilter(iface); + return IUnknown_AddRef(This->outerUnknown); +} + +static ULONG WINAPI AudioRecord_Release(IBaseFilter *iface) +{ + AudioRecord *This = impl_from_IBaseFilter(iface); + return IUnknown_Release(This->outerUnknown); +} + +static HRESULT WINAPI AudioRecord_Stop(IBaseFilter *iface) +{ + AudioRecord *This = impl_from_IBaseFilter(iface); + FIXME("(%p): stub\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI AudioRecord_Pause(IBaseFilter *iface) +{ + AudioRecord *This = impl_from_IBaseFilter(iface); + FIXME("(%p): stub\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI AudioRecord_Run(IBaseFilter *iface, REFERENCE_TIME tStart) +{ + AudioRecord *This = impl_from_IBaseFilter(iface); + FIXME("(%p, %x%08x): stub\n", This, (ULONG)(tStart >> 32), (ULONG)tStart); + return E_NOTIMPL; +} + +static HRESULT WINAPI AudioRecord_FindPin(IBaseFilter *iface, LPCWSTR Id, IPin **ppPin) +{ + AudioRecord *This = impl_from_IBaseFilter(iface); + FIXME("(%p)->(%s, %p): stub\n", This, debugstr_w(Id), ppPin); + return E_NOTIMPL; +} + +static const IBaseFilterVtbl AudioRecordVtbl = { + AudioRecord_QueryInterface, + AudioRecord_AddRef, + AudioRecord_Release, + BaseFilterImpl_GetClassID, + AudioRecord_Stop, + AudioRecord_Pause, + AudioRecord_Run, + BaseFilterImpl_GetState, + BaseFilterImpl_SetSyncSource, + BaseFilterImpl_GetSyncSource, + BaseFilterImpl_EnumPins, + AudioRecord_FindPin, + BaseFilterImpl_QueryFilterInfo, + BaseFilterImpl_JoinFilterGraph, + BaseFilterImpl_QueryVendorInfo +}; + +static IPin* WINAPI AudioRecord_GetPin(BaseFilter *iface, int pos) +{ + AudioRecord *This = impl_from_BaseFilter(iface); + FIXME("(%p, %d): stub\n", This, pos); + return NULL; +} + +static LONG WINAPI AudioRecord_GetPinCount(BaseFilter *iface) +{ + AudioRecord *This = impl_from_BaseFilter(iface); + FIXME("(%p): stub\n", This); + return 0; +} + +static const BaseFilterFuncTable AudioRecordFuncs = { + AudioRecord_GetPin, + AudioRecord_GetPinCount +}; + +static HRESULT WINAPI PPB_QueryInterface(IPersistPropertyBag *iface, REFIID riid, LPVOID *ppv) +{ + AudioRecord *This = impl_from_IPersistPropertyBag(iface); + return IUnknown_QueryInterface(This->outerUnknown, riid, ppv); +} + +static ULONG WINAPI PPB_AddRef(IPersistPropertyBag *iface) +{ + AudioRecord *This = impl_from_IPersistPropertyBag(iface); + return IUnknown_AddRef(This->outerUnknown); +} + +static ULONG WINAPI PPB_Release(IPersistPropertyBag *iface) +{ + AudioRecord *This = impl_from_IPersistPropertyBag(iface); + return IUnknown_Release(This->outerUnknown); +} + +static HRESULT WINAPI PPB_GetClassID(IPersistPropertyBag *iface, CLSID *pClassID) +{ + AudioRecord *This = impl_from_IPersistPropertyBag(iface); + TRACE("(%p/%p)->(%p)\n", iface, This, pClassID); + return IBaseFilter_GetClassID(&This->filter.IBaseFilter_iface, pClassID); +} + +static HRESULT WINAPI PPB_InitNew(IPersistPropertyBag *iface) +{ + AudioRecord *This = impl_from_IPersistPropertyBag(iface); + FIXME("(%p/%p)->(): stub\n", iface, This); + return E_NOTIMPL; +} + +static HRESULT WINAPI PPB_Load(IPersistPropertyBag *iface, IPropertyBag *pPropBag, + IErrorLog *pErrorLog) +{ + AudioRecord *This = impl_from_IPersistPropertyBag(iface); + HRESULT hr; + VARIANT var; + static const WCHAR WaveInIDW[] = {'W','a','v','e','I','n','I','D',0}; + + TRACE("(%p/%p)->(%p, %p)\n", iface, This, pPropBag, pErrorLog); + + V_VT(&var) = VT_I4; + hr = IPropertyBag_Read(pPropBag, WaveInIDW, &var, pErrorLog); + if (SUCCEEDED(hr)) + { + FIXME("FIXME: implement opening waveIn device %d\n", V_I4(&var)); + } + + return hr; +} + +static HRESULT WINAPI PPB_Save(IPersistPropertyBag *iface, IPropertyBag *pPropBag, + BOOL fClearDirty, BOOL fSaveAllProperties) +{ + AudioRecord *This = impl_from_IPersistPropertyBag(iface); + FIXME("(%p/%p)->(%p, %u, %u): stub\n", iface, This, pPropBag, fClearDirty, fSaveAllProperties); + return E_NOTIMPL; +} + +static const IPersistPropertyBagVtbl PersistPropertyBagVtbl = +{ + PPB_QueryInterface, + PPB_AddRef, + PPB_Release, + PPB_GetClassID, + PPB_InitNew, + PPB_Load, + PPB_Save +}; + +IUnknown* WINAPI QCAP_createAudioCaptureFilter(IUnknown *outer, HRESULT *phr) +{ + HRESULT hr; + AudioRecord *This = NULL; + + FIXME("(%p, %p): the entire CLSID_AudioRecord implementation is just stubs\n", outer, phr); + + This = CoTaskMemAlloc(sizeof(*This)); + if (This == NULL) { + hr = E_OUTOFMEMORY; + goto end; + } + memset(This, 0, sizeof(*This)); + This->IUnknown_iface.lpVtbl = &UnknownVtbl; + This->IPersistPropertyBag_iface.lpVtbl = &PersistPropertyBagVtbl; + if (outer) + This->outerUnknown = outer; + else + This->outerUnknown = &This->IUnknown_iface; + + hr = BaseFilter_Init(&This->filter, &AudioRecordVtbl, &CLSID_AudioRecord, + (DWORD_PTR)(__FILE__ ": AudioRecord.csFilter"), &AudioRecordFuncs); + +end: + *phr = hr; + if (SUCCEEDED(hr)) { + return (IUnknown*)&This->filter.IBaseFilter_iface; + } else { + if (This) + IBaseFilter_Release(&This->filter.IBaseFilter_iface); + return NULL; + } +} diff --git a/dlls/qcap/qcap_main.c b/dlls/qcap/qcap_main.c index 78b84844da6..b3798502a85 100644 --- a/dlls/qcap/qcap_main.c +++ b/dlls/qcap/qcap_main.c @@ -77,7 +77,7 @@ FactoryTemplate const g_Templates[] = { { wAudioCaptureFilter, &CLSID_AudioRecord, - NULL, /* FIXME: Implement QCAP_createAudioCaptureFilter */ + QCAP_createAudioCaptureFilter, NULL },{ wAVICompressor,