mirror of
git://source.winehq.org/git/wine.git
synced 2024-09-06 22:51:20 +00:00
qcap: Reimplement COM registration and vending locally.
Signed-off-by: Zebediah Figura <z.figura12@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
cf376c96e8
commit
7bcb8e74ce
|
@ -8,7 +8,6 @@ C_SRCS = \
|
||||||
avico.c \
|
avico.c \
|
||||||
avimux.c \
|
avimux.c \
|
||||||
capturegraph.c \
|
capturegraph.c \
|
||||||
dllfunc.c \
|
|
||||||
filter.c \
|
filter.c \
|
||||||
mediatype.c \
|
mediatype.c \
|
||||||
pin.c \
|
pin.c \
|
||||||
|
@ -18,3 +17,6 @@ C_SRCS = \
|
||||||
vfwcapture.c
|
vfwcapture.c
|
||||||
|
|
||||||
RC_SRCS = version.rc
|
RC_SRCS = version.rc
|
||||||
|
|
||||||
|
IDL_SRCS = \
|
||||||
|
qcap_classes.idl
|
||||||
|
|
|
@ -154,22 +154,18 @@ static const IPersistPropertyBagVtbl PersistPropertyBagVtbl =
|
||||||
PPB_Save
|
PPB_Save
|
||||||
};
|
};
|
||||||
|
|
||||||
IUnknown* WINAPI QCAP_createAudioCaptureFilter(IUnknown *outer, HRESULT *phr)
|
HRESULT audio_record_create(IUnknown *outer, IUnknown **out)
|
||||||
{
|
{
|
||||||
AudioRecord *This = NULL;
|
AudioRecord *object;
|
||||||
|
|
||||||
FIXME("(%p, %p): the entire CLSID_AudioRecord implementation is just stubs\n", outer, phr);
|
if (!(object = CoTaskMemAlloc(sizeof(*object))))
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
memset(object, 0, sizeof(*object));
|
||||||
|
|
||||||
This = CoTaskMemAlloc(sizeof(*This));
|
object->IPersistPropertyBag_iface.lpVtbl = &PersistPropertyBagVtbl;
|
||||||
if (This == NULL) {
|
strmbase_filter_init(&object->filter, outer, &CLSID_AudioRecord, &filter_ops);
|
||||||
*phr = E_OUTOFMEMORY;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
memset(This, 0, sizeof(*This));
|
|
||||||
This->IPersistPropertyBag_iface.lpVtbl = &PersistPropertyBagVtbl;
|
|
||||||
|
|
||||||
strmbase_filter_init(&This->filter, outer, &CLSID_AudioRecord, &filter_ops);
|
TRACE("Created audio recorder %p.\n", object);
|
||||||
|
*out = &object->filter.IUnknown_inner;
|
||||||
*phr = S_OK;
|
return S_OK;
|
||||||
return &This->filter.IUnknown_inner;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -480,25 +480,22 @@ static const struct strmbase_source_ops source_ops =
|
||||||
.pfnDecideAllocator = AVICompressorOut_DecideAllocator,
|
.pfnDecideAllocator = AVICompressorOut_DecideAllocator,
|
||||||
};
|
};
|
||||||
|
|
||||||
IUnknown* WINAPI QCAP_createAVICompressor(IUnknown *outer, HRESULT *phr)
|
HRESULT avi_compressor_create(IUnknown *outer, IUnknown **out)
|
||||||
{
|
{
|
||||||
static const WCHAR source_name[] = {'O','u','t',0};
|
static const WCHAR source_name[] = {'O','u','t',0};
|
||||||
static const WCHAR sink_name[] = {'I','n',0};
|
static const WCHAR sink_name[] = {'I','n',0};
|
||||||
AVICompressor *compressor;
|
AVICompressor *object;
|
||||||
|
|
||||||
compressor = heap_alloc_zero(sizeof(*compressor));
|
if (!(object = heap_alloc_zero(sizeof(*object))))
|
||||||
if(!compressor) {
|
return E_OUTOFMEMORY;
|
||||||
*phr = E_NOINTERFACE;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
strmbase_filter_init(&compressor->filter, outer, &CLSID_AVICo, &filter_ops);
|
strmbase_filter_init(&object->filter, outer, &CLSID_AVICo, &filter_ops);
|
||||||
|
object->IPersistPropertyBag_iface.lpVtbl = &PersistPropertyBagVtbl;
|
||||||
|
|
||||||
compressor->IPersistPropertyBag_iface.lpVtbl = &PersistPropertyBagVtbl;
|
strmbase_sink_init(&object->sink, &object->filter, sink_name, &sink_ops, NULL);
|
||||||
|
strmbase_source_init(&object->source, &object->filter, source_name, &source_ops);
|
||||||
|
|
||||||
strmbase_sink_init(&compressor->sink, &compressor->filter, sink_name, &sink_ops, NULL);
|
TRACE("Created AVI compressor %p.\n", object);
|
||||||
strmbase_source_init(&compressor->source, &compressor->filter, source_name, &source_ops);
|
*out = &object->filter.IUnknown_inner;
|
||||||
|
return S_OK;
|
||||||
*phr = S_OK;
|
|
||||||
return &compressor->filter.IUnknown_inner;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1835,7 +1835,7 @@ static HRESULT create_input_pin(AviMux *avimux)
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
IUnknown * WINAPI QCAP_createAVIMux(IUnknown *outer, HRESULT *phr)
|
HRESULT avi_mux_create(IUnknown *outer, IUnknown **out)
|
||||||
{
|
{
|
||||||
static const WCHAR output_name[] = {'A','V','I',' ','O','u','t',0};
|
static const WCHAR output_name[] = {'A','V','I',' ','O','u','t',0};
|
||||||
|
|
||||||
|
@ -1843,11 +1843,8 @@ IUnknown * WINAPI QCAP_createAVIMux(IUnknown *outer, HRESULT *phr)
|
||||||
PIN_INFO info;
|
PIN_INFO info;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
avimux = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(AviMux));
|
if (!(avimux = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(AviMux))))
|
||||||
if(!avimux) {
|
return E_OUTOFMEMORY;
|
||||||
*phr = E_OUTOFMEMORY;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
strmbase_filter_init(&avimux->filter, outer, &CLSID_AviDest, &filter_ops);
|
strmbase_filter_init(&avimux->filter, outer, &CLSID_AviDest, &filter_ops);
|
||||||
avimux->IConfigAviMux_iface.lpVtbl = &ConfigAviMuxVtbl;
|
avimux->IConfigAviMux_iface.lpVtbl = &ConfigAviMuxVtbl;
|
||||||
|
@ -1870,13 +1867,13 @@ IUnknown * WINAPI QCAP_createAVIMux(IUnknown *outer, HRESULT *phr)
|
||||||
strmbase_source_cleanup(&avimux->source);
|
strmbase_source_cleanup(&avimux->source);
|
||||||
strmbase_filter_cleanup(&avimux->filter);
|
strmbase_filter_cleanup(&avimux->filter);
|
||||||
HeapFree(GetProcessHeap(), 0, avimux);
|
HeapFree(GetProcessHeap(), 0, avimux);
|
||||||
*phr = hr;
|
return hr;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
avimux->interleave = 10000000;
|
avimux->interleave = 10000000;
|
||||||
|
|
||||||
|
TRACE("Created AVI mux %p.\n", avimux);
|
||||||
ObjectRefCount(TRUE);
|
ObjectRefCount(TRUE);
|
||||||
*phr = S_OK;
|
*out = &avimux->filter.IUnknown_inner;
|
||||||
return &avimux->filter.IUnknown_inner;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,33 +74,27 @@ static inline CaptureGraphImpl *impl_from_ICaptureGraphBuilder2(ICaptureGraphBui
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
IUnknown * CALLBACK QCAP_createCaptureGraphBuilder2(IUnknown *pUnkOuter,
|
HRESULT capture_graph_create(IUnknown *outer, IUnknown **out)
|
||||||
HRESULT *phr)
|
|
||||||
{
|
{
|
||||||
CaptureGraphImpl * pCapture = NULL;
|
CaptureGraphImpl *object;
|
||||||
|
|
||||||
TRACE("(%p, %p)\n", pUnkOuter, phr);
|
if (outer)
|
||||||
|
return CLASS_E_NOAGGREGATION;
|
||||||
|
|
||||||
*phr = CLASS_E_NOAGGREGATION;
|
if (!(object = CoTaskMemAlloc(sizeof(*object))))
|
||||||
if (pUnkOuter)
|
return E_OUTOFMEMORY;
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
*phr = E_OUTOFMEMORY;
|
|
||||||
|
|
||||||
pCapture = CoTaskMemAlloc(sizeof(CaptureGraphImpl));
|
object->ICaptureGraphBuilder2_iface.lpVtbl = &builder2_Vtbl;
|
||||||
if (pCapture)
|
object->ICaptureGraphBuilder_iface.lpVtbl = &builder_Vtbl;
|
||||||
{
|
object->ref = 1;
|
||||||
pCapture->ICaptureGraphBuilder2_iface.lpVtbl = &builder2_Vtbl;
|
object->mygraph = NULL;
|
||||||
pCapture->ICaptureGraphBuilder_iface.lpVtbl = &builder_Vtbl;
|
InitializeCriticalSection(&object->csFilter);
|
||||||
pCapture->ref = 1;
|
object->csFilter.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": CaptureGraphImpl.csFilter");
|
||||||
pCapture->mygraph = NULL;
|
|
||||||
InitializeCriticalSection(&pCapture->csFilter);
|
TRACE("Created capture graph builder %p.\n", object);
|
||||||
pCapture->csFilter.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": CaptureGraphImpl.csFilter");
|
ObjectRefCount(TRUE);
|
||||||
*phr = S_OK;
|
*out = (IUnknown *)&object->ICaptureGraphBuilder_iface;
|
||||||
ObjectRefCount(TRUE);
|
return S_OK;
|
||||||
}
|
|
||||||
return (IUnknown *)&pCapture->ICaptureGraphBuilder_iface;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI
|
static HRESULT WINAPI
|
||||||
|
|
70
dlls/qcap/qcap_classes.idl
Normal file
70
dlls/qcap/qcap_classes.idl
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* COM classes for qcap
|
||||||
|
*
|
||||||
|
* Copyright 2019 Zebediah Figura
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma makedep register
|
||||||
|
|
||||||
|
[
|
||||||
|
helpstring("Audio Capture Filter"),
|
||||||
|
threading(both),
|
||||||
|
uuid(e30629d2-27e5-11ce-875d-00608cb78066)
|
||||||
|
]
|
||||||
|
coclass AudioRecord {}
|
||||||
|
|
||||||
|
[
|
||||||
|
helpstring("Audio Capture Filter"),
|
||||||
|
threading(both),
|
||||||
|
uuid(d76e2820-1563-11cf-ac98-00aa004c0fa9)
|
||||||
|
]
|
||||||
|
coclass AVICo {}
|
||||||
|
|
||||||
|
[
|
||||||
|
helpstring("AVI mux"),
|
||||||
|
threading(both),
|
||||||
|
uuid(e2510970-f137-11ce-8b67-00aa00a3f1a6)
|
||||||
|
]
|
||||||
|
coclass AviDest {}
|
||||||
|
|
||||||
|
[
|
||||||
|
helpstring("Capture Graph Builder"),
|
||||||
|
threading(both),
|
||||||
|
uuid(bf87b6e0-8c27-11d0-b3f0-00aa003761c5)
|
||||||
|
]
|
||||||
|
coclass CaptureGraphBuilder {}
|
||||||
|
|
||||||
|
[
|
||||||
|
helpstring("Capture Graph Builder 2"),
|
||||||
|
threading(both),
|
||||||
|
uuid(bf87b6e1-8c27-11d0-b3f0-00aa003761c5)
|
||||||
|
]
|
||||||
|
coclass CaptureGraphBuilder2 {}
|
||||||
|
|
||||||
|
[
|
||||||
|
helpstring("Smart Tee Filter"),
|
||||||
|
threading(both),
|
||||||
|
uuid(cc58e280-8aa1-11d1-b3f1-00aa003761c5)
|
||||||
|
]
|
||||||
|
coclass SmartTee {}
|
||||||
|
|
||||||
|
[
|
||||||
|
helpstring("VFW Capture Filter"),
|
||||||
|
threading(both),
|
||||||
|
uuid(1b544c22-fd0b-11ce-8c63-00aa0044b51e)
|
||||||
|
]
|
||||||
|
coclass VfwCapture {}
|
|
@ -1,8 +1,9 @@
|
||||||
/*
|
/*
|
||||||
* Qcap implementation, dllentry points
|
* DirectShow capture
|
||||||
*
|
*
|
||||||
* Copyright (C) 2003 Dominik Strasser
|
* Copyright (C) 2003 Dominik Strasser
|
||||||
* Copyright (C) 2005 Rolf Kalbermatter
|
* Copyright (C) 2005 Rolf Kalbermatter
|
||||||
|
* Copyright (C) 2019 Zebediah Figura
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
@ -25,7 +26,8 @@
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
#define COBJMACROS
|
#define COBJMACROS
|
||||||
|
#define NONAMELESSSTRUCT
|
||||||
|
#define NONAMELESSUNION
|
||||||
#include "windef.h"
|
#include "windef.h"
|
||||||
#include "winbase.h"
|
#include "winbase.h"
|
||||||
#include "wingdi.h"
|
#include "wingdi.h"
|
||||||
|
@ -33,6 +35,7 @@
|
||||||
#include "objbase.h"
|
#include "objbase.h"
|
||||||
#include "uuids.h"
|
#include "uuids.h"
|
||||||
#include "strmif.h"
|
#include "strmif.h"
|
||||||
|
#include "rpcproxy.h"
|
||||||
|
|
||||||
#include "qcap_main.h"
|
#include "qcap_main.h"
|
||||||
|
|
||||||
|
@ -41,132 +44,207 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(qcap);
|
WINE_DEFAULT_DEBUG_CHANNEL(qcap);
|
||||||
|
|
||||||
|
static HINSTANCE qcap_instance;
|
||||||
|
|
||||||
static LONG objects_ref = 0;
|
static LONG objects_ref = 0;
|
||||||
|
|
||||||
static const WCHAR wAudioCaptureFilter[] =
|
struct class_factory
|
||||||
{'A','u','d','i','o',' ','C','a','p','t','u','r','e',' ','F','i','l','t','e','r',0};
|
{
|
||||||
static const WCHAR wAVICompressor[] =
|
IClassFactory IClassFactory_iface;
|
||||||
{'A','V','I',' ','C','o','m','p','r','e','s','s','o','r',0};
|
HRESULT (*create_instance)(IUnknown *outer, IUnknown **out);
|
||||||
static const WCHAR wVFWCaptFilter[] =
|
|
||||||
{'V','F','W',' ','C','a','p','t','u','r','e',' ','F','i','l','t','e','r',0};
|
|
||||||
static const WCHAR wVFWCaptFilterProp[] =
|
|
||||||
{'V','F','W',' ','C','a','p','t','u','r','e',' ','F','i','l','t','e','r',' ',
|
|
||||||
'P','r','o','p','e','r','t','y',' ','P','a','g','e',0};
|
|
||||||
static const WCHAR wAVIMux[] =
|
|
||||||
{'A','V','I',' ','m','u','x',0};
|
|
||||||
static const WCHAR wAVIMuxPropPage[] =
|
|
||||||
{'A','V','I',' ','m','u','x',' ','P','r','o','p','e','r','t','y',' ','P','a','g','e',0};
|
|
||||||
static const WCHAR wAVIMuxPropPage1[] =
|
|
||||||
{'A','V','I',' ','m','u','x',' ','P','r','o','p','e','r','t','y',' ','P','a','g','e','1',0};
|
|
||||||
static const WCHAR wFileWriter[] =
|
|
||||||
{'F','i','l','e',' ','W','r','i','t','e','r',0};
|
|
||||||
static const WCHAR wCaptGraphBuilder[] =
|
|
||||||
{'C','a','p','t','u','r','e',' ','G','r','a','p','h',' ','B','u','i','l','d','e','r',0};
|
|
||||||
static const WCHAR wCaptGraphBuilder2[] =
|
|
||||||
{'C','a','p','t','u','r','e',' ','G','r','a','p','h',' ','B','u','i','l','d','e','r','2',0};
|
|
||||||
static const WCHAR wInfPinTeeFilter[] =
|
|
||||||
{'I','n','f','i','n','i','t','e',' ','P','i','n',' ','T','e','e',' ','F','i',
|
|
||||||
'l','t','e','r',0};
|
|
||||||
static const WCHAR wSmartTeeFilter[] =
|
|
||||||
{'S','m','a','r','t',' ','T','e','e',' ','F','i','l','t','e','r',0};
|
|
||||||
static const WCHAR wAudioInMixerProp[] =
|
|
||||||
{'A','u','d','i','o','I','n','p','u','t','M','i','x','e','r',' ','P','r','o',
|
|
||||||
'p','e','r','t','y',' ','P','a','g','e',0};
|
|
||||||
|
|
||||||
FactoryTemplate const g_Templates[] = {
|
|
||||||
{
|
|
||||||
wAudioCaptureFilter,
|
|
||||||
&CLSID_AudioRecord,
|
|
||||||
QCAP_createAudioCaptureFilter,
|
|
||||||
NULL
|
|
||||||
},{
|
|
||||||
wAVICompressor,
|
|
||||||
&CLSID_AVICo,
|
|
||||||
QCAP_createAVICompressor,
|
|
||||||
NULL
|
|
||||||
},{
|
|
||||||
wVFWCaptFilter,
|
|
||||||
&CLSID_VfwCapture,
|
|
||||||
QCAP_createVFWCaptureFilter,
|
|
||||||
NULL
|
|
||||||
},{
|
|
||||||
wVFWCaptFilterProp,
|
|
||||||
&CLSID_CaptureProperties,
|
|
||||||
NULL, /* FIXME: Implement QCAP_createVFWCaptureFilterPropertyPage */
|
|
||||||
NULL
|
|
||||||
},{
|
|
||||||
wAVIMux,
|
|
||||||
&CLSID_AviDest,
|
|
||||||
QCAP_createAVIMux,
|
|
||||||
NULL
|
|
||||||
},{
|
|
||||||
wAVIMuxPropPage,
|
|
||||||
&CLSID_AviMuxProptyPage,
|
|
||||||
NULL, /* FIXME: Implement QCAP_createAVIMuxPropertyPage */
|
|
||||||
NULL
|
|
||||||
},{
|
|
||||||
wAVIMuxPropPage1,
|
|
||||||
&CLSID_AviMuxProptyPage1,
|
|
||||||
NULL, /* FIXME: Implement QCAP_createAVIMuxPropertyPage1 */
|
|
||||||
NULL
|
|
||||||
},{
|
|
||||||
wFileWriter,
|
|
||||||
&CLSID_FileWriter,
|
|
||||||
NULL, /* FIXME: Implement QCAP_createFileWriter */
|
|
||||||
NULL
|
|
||||||
},{
|
|
||||||
wCaptGraphBuilder,
|
|
||||||
&CLSID_CaptureGraphBuilder,
|
|
||||||
QCAP_createCaptureGraphBuilder2,
|
|
||||||
NULL
|
|
||||||
},{
|
|
||||||
wCaptGraphBuilder2,
|
|
||||||
&CLSID_CaptureGraphBuilder2,
|
|
||||||
QCAP_createCaptureGraphBuilder2,
|
|
||||||
NULL
|
|
||||||
},{
|
|
||||||
wInfPinTeeFilter,
|
|
||||||
&CLSID_InfTee,
|
|
||||||
NULL, /* FIXME: Implement QCAP_createInfinitePinTeeFilter */
|
|
||||||
NULL
|
|
||||||
},{
|
|
||||||
wSmartTeeFilter,
|
|
||||||
&CLSID_SmartTee,
|
|
||||||
QCAP_createSmartTeeFilter,
|
|
||||||
NULL
|
|
||||||
},{
|
|
||||||
wAudioInMixerProp,
|
|
||||||
&CLSID_AudioInputMixerProperties,
|
|
||||||
NULL, /* FIXME: Implement QCAP_createAudioInputMixerPropertyPage */
|
|
||||||
NULL
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const int g_cTemplates = ARRAY_SIZE(g_Templates);
|
static inline struct class_factory *impl_from_IClassFactory(IClassFactory *iface)
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* Dll EntryPoint (QCAP.@)
|
|
||||||
*/
|
|
||||||
BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
|
|
||||||
{
|
{
|
||||||
return STRMBASE_DllMain(hInstDLL,fdwReason,lpv);
|
return CONTAINING_RECORD(iface, struct class_factory, IClassFactory_iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
static HRESULT WINAPI class_factory_QueryInterface(IClassFactory *iface, REFIID iid, void **out)
|
||||||
* DllGetClassObject
|
|
||||||
*/
|
|
||||||
HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
|
|
||||||
{
|
{
|
||||||
return STRMBASE_DllGetClassObject( rclsid, riid, ppv );
|
TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
|
||||||
|
|
||||||
|
if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IClassFactory))
|
||||||
|
{
|
||||||
|
*out = iface;
|
||||||
|
IClassFactory_AddRef(iface);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out = NULL;
|
||||||
|
WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
|
||||||
|
return E_NOINTERFACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ULONG WINAPI class_factory_AddRef(IClassFactory *iface)
|
||||||
|
{
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG WINAPI class_factory_Release(IClassFactory *iface)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI class_factory_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID iid, void **out)
|
||||||
|
{
|
||||||
|
struct class_factory *factory = impl_from_IClassFactory(iface);
|
||||||
|
IUnknown *unk;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
TRACE("iface %p, outer %p, iid %s, out %p.\n", iface, outer, debugstr_guid(iid), out);
|
||||||
|
|
||||||
|
if (outer && !IsEqualGUID(iid, &IID_IUnknown))
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
|
||||||
|
*out = NULL;
|
||||||
|
if (SUCCEEDED(hr = factory->create_instance(outer, &unk)))
|
||||||
|
{
|
||||||
|
hr = IUnknown_QueryInterface(unk, iid, out);
|
||||||
|
IUnknown_Release(unk);
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI class_factory_LockServer(IClassFactory *iface, BOOL lock)
|
||||||
|
{
|
||||||
|
TRACE("iface %p, lock %d.\n", iface, lock);
|
||||||
|
|
||||||
|
if (lock)
|
||||||
|
InterlockedIncrement(&objects_ref);
|
||||||
|
else
|
||||||
|
InterlockedDecrement(&objects_ref);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const IClassFactoryVtbl class_factory_vtbl =
|
||||||
|
{
|
||||||
|
class_factory_QueryInterface,
|
||||||
|
class_factory_AddRef,
|
||||||
|
class_factory_Release,
|
||||||
|
class_factory_CreateInstance,
|
||||||
|
class_factory_LockServer,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct class_factory audio_record_cf = {{&class_factory_vtbl}, audio_record_create};
|
||||||
|
static struct class_factory avi_compressor_cf = {{&class_factory_vtbl}, avi_compressor_create};
|
||||||
|
static struct class_factory avi_mux_cf = {{&class_factory_vtbl}, avi_mux_create};
|
||||||
|
static struct class_factory capture_graph_cf = {{&class_factory_vtbl}, capture_graph_create};
|
||||||
|
static struct class_factory smart_tee_cf = {{&class_factory_vtbl}, smart_tee_create};
|
||||||
|
static struct class_factory vfw_capture_cf = {{&class_factory_vtbl}, vfw_capture_create};
|
||||||
|
|
||||||
|
BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, void *reserved)
|
||||||
|
{
|
||||||
|
if (reason == DLL_PROCESS_ATTACH)
|
||||||
|
{
|
||||||
|
qcap_instance = instance;
|
||||||
|
DisableThreadLibraryCalls(instance);
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID iid, void **out)
|
||||||
|
{
|
||||||
|
struct class_factory *factory;
|
||||||
|
|
||||||
|
TRACE("clsid %s, iid %s, out %p.\n", debugstr_guid(clsid), debugstr_guid(iid), out);
|
||||||
|
|
||||||
|
if (IsEqualGUID(clsid, &CLSID_AudioRecord))
|
||||||
|
factory = &audio_record_cf;
|
||||||
|
else if (IsEqualGUID(clsid, &CLSID_AVICo))
|
||||||
|
factory = &avi_compressor_cf;
|
||||||
|
else if (IsEqualGUID(clsid, &CLSID_AviDest))
|
||||||
|
factory = &avi_mux_cf;
|
||||||
|
else if (IsEqualGUID(clsid, &CLSID_CaptureGraphBuilder))
|
||||||
|
factory = &capture_graph_cf;
|
||||||
|
else if (IsEqualGUID(clsid, &CLSID_CaptureGraphBuilder2))
|
||||||
|
factory = &capture_graph_cf;
|
||||||
|
else if (IsEqualGUID(clsid, &CLSID_SmartTee))
|
||||||
|
factory = &smart_tee_cf;
|
||||||
|
else if (IsEqualGUID(clsid, &CLSID_VfwCapture))
|
||||||
|
factory = &vfw_capture_cf;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FIXME("%s not implemented, returning CLASS_E_CLASSNOTAVAILABLE.\n", debugstr_guid(clsid));
|
||||||
|
return CLASS_E_CLASSNOTAVAILABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return IClassFactory_QueryInterface(&factory->IClassFactory_iface, iid, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const REGPINTYPES reg_avi_mux_sink_mt = {&MEDIATYPE_Stream, &MEDIASUBTYPE_Avi};
|
||||||
|
|
||||||
|
static const REGFILTERPINS2 reg_avi_mux_pins[1] =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
.cInstances = 1,
|
||||||
|
.nMediaTypes = 1,
|
||||||
|
.lpMediaType = ®_avi_mux_sink_mt,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const REGFILTER2 reg_avi_mux =
|
||||||
|
{
|
||||||
|
.dwVersion = 2,
|
||||||
|
.dwMerit = MERIT_DO_NOT_USE,
|
||||||
|
.u.s2.cPins2 = 1,
|
||||||
|
.u.s2.rgPins2 = reg_avi_mux_pins,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const REGPINTYPES reg_video_mt = {&MEDIATYPE_Video, &GUID_NULL};
|
||||||
|
|
||||||
|
static const REGFILTERPINS2 reg_smart_tee_pins[3] =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
.cInstances = 1,
|
||||||
|
.nMediaTypes = 1,
|
||||||
|
.lpMediaType = ®_video_mt,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.dwFlags = REG_PINFLAG_B_OUTPUT,
|
||||||
|
.cInstances = 1,
|
||||||
|
.nMediaTypes = 1,
|
||||||
|
.lpMediaType = ®_video_mt,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.dwFlags = REG_PINFLAG_B_OUTPUT,
|
||||||
|
.cInstances = 1,
|
||||||
|
.nMediaTypes = 1,
|
||||||
|
.lpMediaType = ®_video_mt,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const REGFILTER2 reg_smart_tee =
|
||||||
|
{
|
||||||
|
.dwVersion = 2,
|
||||||
|
.dwMerit = MERIT_DO_NOT_USE,
|
||||||
|
.u.s2.cPins2 = 3,
|
||||||
|
.u.s2.rgPins2 = reg_smart_tee_pins,
|
||||||
|
};
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* DllRegisterServer (QCAP.@)
|
* DllRegisterServer (QCAP.@)
|
||||||
*/
|
*/
|
||||||
HRESULT WINAPI DllRegisterServer(void)
|
HRESULT WINAPI DllRegisterServer(void)
|
||||||
{
|
{
|
||||||
TRACE("()\n");
|
static const WCHAR avi_muxW[] = {'A','V','I',' ','M','u','x',0};
|
||||||
return AMovieDllRegisterServer2(TRUE);
|
static const WCHAR smart_teeW[] = {'S','m','a','r','t',' ','T','e','e',0};
|
||||||
|
IFilterMapper2 *mapper;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
if (FAILED(hr = __wine_register_resources( qcap_instance )))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
if (FAILED(hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER,
|
||||||
|
&IID_IFilterMapper2, (void **)&mapper)))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
IFilterMapper2_RegisterFilter(mapper, &CLSID_AviDest, avi_muxW,
|
||||||
|
NULL, NULL, NULL, ®_avi_mux);
|
||||||
|
IFilterMapper2_RegisterFilter(mapper, &CLSID_SmartTee, smart_teeW,
|
||||||
|
NULL, NULL, NULL, ®_smart_tee);
|
||||||
|
|
||||||
|
IFilterMapper2_Release(mapper);
|
||||||
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
@ -174,8 +252,21 @@ HRESULT WINAPI DllRegisterServer(void)
|
||||||
*/
|
*/
|
||||||
HRESULT WINAPI DllUnregisterServer(void)
|
HRESULT WINAPI DllUnregisterServer(void)
|
||||||
{
|
{
|
||||||
TRACE("\n");
|
IFilterMapper2 *mapper;
|
||||||
return AMovieDllRegisterServer2(FALSE);
|
HRESULT hr;
|
||||||
|
|
||||||
|
if (FAILED(hr = __wine_unregister_resources( qcap_instance )))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
if (FAILED(hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER,
|
||||||
|
&IID_IFilterMapper2, (void **)&mapper)))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
IFilterMapper2_UnregisterFilter(mapper, NULL, NULL, &CLSID_AviDest);
|
||||||
|
IFilterMapper2_UnregisterFilter(mapper, NULL, NULL, &CLSID_SmartTee);
|
||||||
|
|
||||||
|
IFilterMapper2_Release(mapper);
|
||||||
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
@ -183,11 +274,9 @@ HRESULT WINAPI DllUnregisterServer(void)
|
||||||
*/
|
*/
|
||||||
HRESULT WINAPI DllCanUnloadNow(void)
|
HRESULT WINAPI DllCanUnloadNow(void)
|
||||||
{
|
{
|
||||||
TRACE("\n");
|
TRACE(".\n");
|
||||||
|
|
||||||
if (STRMBASE_DllCanUnloadNow() == S_OK && objects_ref == 0)
|
return objects_ref ? S_FALSE : S_OK;
|
||||||
return S_OK;
|
|
||||||
return S_FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD ObjectRefCount(BOOL increment)
|
DWORD ObjectRefCount(BOOL increment)
|
||||||
|
|
|
@ -25,18 +25,11 @@
|
||||||
|
|
||||||
extern DWORD ObjectRefCount(BOOL increment) DECLSPEC_HIDDEN;
|
extern DWORD ObjectRefCount(BOOL increment) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
extern IUnknown * WINAPI QCAP_createAudioCaptureFilter(IUnknown *pUnkOuter, HRESULT *phr) DECLSPEC_HIDDEN;
|
HRESULT audio_record_create(IUnknown *outer, IUnknown **out) DECLSPEC_HIDDEN;
|
||||||
extern IUnknown * WINAPI QCAP_createAVICompressor(IUnknown *pUnkOuter, HRESULT *phr) DECLSPEC_HIDDEN;
|
HRESULT avi_compressor_create(IUnknown *outer, IUnknown **out) DECLSPEC_HIDDEN;
|
||||||
extern IUnknown * WINAPI QCAP_createVFWCaptureFilter(IUnknown *pUnkOuter, HRESULT *phr) DECLSPEC_HIDDEN;
|
HRESULT avi_mux_create(IUnknown *outer, IUnknown **out) DECLSPEC_HIDDEN;
|
||||||
extern IUnknown * WINAPI QCAP_createVFWCaptureFilterPropertyPage(IUnknown *pUnkOuter, HRESULT *phr) DECLSPEC_HIDDEN;
|
HRESULT capture_graph_create(IUnknown *outer, IUnknown **out) DECLSPEC_HIDDEN;
|
||||||
extern IUnknown * WINAPI QCAP_createAVICompressor(IUnknown*,HRESULT*) DECLSPEC_HIDDEN;
|
HRESULT smart_tee_create(IUnknown *outer, IUnknown **out) DECLSPEC_HIDDEN;
|
||||||
extern IUnknown * WINAPI QCAP_createAVIMux(IUnknown *pUnkOuter, HRESULT *phr) DECLSPEC_HIDDEN;
|
HRESULT vfw_capture_create(IUnknown *outer, IUnknown **out) DECLSPEC_HIDDEN;
|
||||||
extern IUnknown * WINAPI QCAP_createAVIMuxPropertyPage(IUnknown *pUnkOuter, HRESULT *phr) DECLSPEC_HIDDEN;
|
|
||||||
extern IUnknown * WINAPI QCAP_createAVIMuxPropertyPage1(IUnknown *pUnkOuter, HRESULT *phr) DECLSPEC_HIDDEN;
|
|
||||||
extern IUnknown * WINAPI QCAP_createFileWriter(IUnknown *pUnkOuter, HRESULT *phr) DECLSPEC_HIDDEN;
|
|
||||||
extern IUnknown * WINAPI QCAP_createCaptureGraphBuilder2(IUnknown *pUnkOuter, HRESULT *phr) DECLSPEC_HIDDEN;
|
|
||||||
extern IUnknown * WINAPI QCAP_createInfinitePinTeeFilter(IUnknown *pUnkOuter, HRESULT *phr) DECLSPEC_HIDDEN;
|
|
||||||
extern IUnknown * WINAPI QCAP_createSmartTeeFilter(IUnknown *pUnkOuter, HRESULT *phr) DECLSPEC_HIDDEN;
|
|
||||||
extern IUnknown * WINAPI QCAP_createAudioInputMixerPropertyPage(IUnknown *pUnkOuter, HRESULT *phr) DECLSPEC_HIDDEN;
|
|
||||||
|
|
||||||
#endif /* _QCAP_MAIN_H_DEFINED */
|
#endif /* _QCAP_MAIN_H_DEFINED */
|
||||||
|
|
|
@ -321,7 +321,7 @@ static const struct strmbase_source_ops preview_ops =
|
||||||
.pfnDecideAllocator = SmartTeeFilterPreview_DecideAllocator,
|
.pfnDecideAllocator = SmartTeeFilterPreview_DecideAllocator,
|
||||||
};
|
};
|
||||||
|
|
||||||
IUnknown* WINAPI QCAP_createSmartTeeFilter(IUnknown *outer, HRESULT *phr)
|
HRESULT smart_tee_create(IUnknown *outer, IUnknown **out)
|
||||||
{
|
{
|
||||||
static const WCHAR captureW[] = {'C','a','p','t','u','r','e',0};
|
static const WCHAR captureW[] = {'C','a','p','t','u','r','e',0};
|
||||||
static const WCHAR previewW[] = {'P','r','e','v','i','e','w',0};
|
static const WCHAR previewW[] = {'P','r','e','v','i','e','w',0};
|
||||||
|
@ -330,10 +330,7 @@ IUnknown* WINAPI QCAP_createSmartTeeFilter(IUnknown *outer, HRESULT *phr)
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
if (!(object = CoTaskMemAlloc(sizeof(*object))))
|
if (!(object = CoTaskMemAlloc(sizeof(*object))))
|
||||||
{
|
return E_OUTOFMEMORY;
|
||||||
*phr = E_OUTOFMEMORY;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
memset(object, 0, sizeof(*object));
|
memset(object, 0, sizeof(*object));
|
||||||
|
|
||||||
strmbase_filter_init(&object->filter, outer, &CLSID_SmartTee, &filter_ops);
|
strmbase_filter_init(&object->filter, outer, &CLSID_SmartTee, &filter_ops);
|
||||||
|
@ -342,14 +339,15 @@ IUnknown* WINAPI QCAP_createSmartTeeFilter(IUnknown *outer, HRESULT *phr)
|
||||||
&IID_IMemAllocator, (void **)&object->sink.pAllocator);
|
&IID_IMemAllocator, (void **)&object->sink.pAllocator);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
*phr = hr;
|
|
||||||
strmbase_filter_cleanup(&object->filter);
|
strmbase_filter_cleanup(&object->filter);
|
||||||
return NULL;
|
CoTaskMemFree(object);
|
||||||
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
strmbase_source_init(&object->capture, &object->filter, captureW, &capture_ops);
|
strmbase_source_init(&object->capture, &object->filter, captureW, &capture_ops);
|
||||||
strmbase_source_init(&object->preview, &object->filter, previewW, &preview_ops);
|
strmbase_source_init(&object->preview, &object->filter, previewW, &preview_ops);
|
||||||
|
|
||||||
*phr = S_OK;
|
TRACE("Created smart tee %p.\n", object);
|
||||||
return &object->filter.IUnknown_inner;
|
*out = &object->filter.IUnknown_inner;
|
||||||
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -563,16 +563,13 @@ static const struct strmbase_source_ops source_ops =
|
||||||
.pfnDecideAllocator = BaseOutputPinImpl_DecideAllocator,
|
.pfnDecideAllocator = BaseOutputPinImpl_DecideAllocator,
|
||||||
};
|
};
|
||||||
|
|
||||||
IUnknown * WINAPI QCAP_createVFWCaptureFilter(IUnknown *outer, HRESULT *phr)
|
HRESULT vfw_capture_create(IUnknown *outer, IUnknown **out)
|
||||||
{
|
{
|
||||||
static const WCHAR source_name[] = {'O','u','t','p','u','t',0};
|
static const WCHAR source_name[] = {'O','u','t','p','u','t',0};
|
||||||
VfwCapture *object;
|
VfwCapture *object;
|
||||||
|
|
||||||
if (!(object = CoTaskMemAlloc(sizeof(*object))))
|
if (!(object = CoTaskMemAlloc(sizeof(*object))))
|
||||||
{
|
return E_OUTOFMEMORY;
|
||||||
*phr = E_OUTOFMEMORY;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
strmbase_filter_init(&object->filter, outer, &CLSID_VfwCapture, &filter_ops);
|
strmbase_filter_init(&object->filter, outer, &CLSID_VfwCapture, &filter_ops);
|
||||||
|
|
||||||
|
@ -587,6 +584,6 @@ IUnknown * WINAPI QCAP_createVFWCaptureFilter(IUnknown *outer, HRESULT *phr)
|
||||||
|
|
||||||
TRACE("Created VFW capture filter %p.\n", object);
|
TRACE("Created VFW capture filter %p.\n", object);
|
||||||
ObjectRefCount(TRUE);
|
ObjectRefCount(TRUE);
|
||||||
*phr = S_OK;
|
*out = &object->filter.IUnknown_inner;
|
||||||
return &object->filter.IUnknown_inner;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue