main.c 10.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*              DirectShow Base Functions (QUARTZ.DLL)
 *
 * Copyright 2002 Lionel Ulmer
 *
 * 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
17
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 19
 */

20 21
#include "wine/debug.h"

22
#include "quartz_private.h"
23 24 25

WINE_DEFAULT_DEBUG_CHANNEL(quartz);

26 27
extern HRESULT WINAPI QUARTZ_DllGetClassObject(REFCLSID, REFIID, LPVOID *);
extern BOOL WINAPI QUARTZ_DllMain(HINSTANCE, DWORD, LPVOID);
28

29
BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, void *reserved)
30
{
31 32
    if (reason == DLL_PROCESS_DETACH && !reserved)
    {
33
        video_window_unregister_class();
34 35
        strmbase_release_typelibs();
    }
36
    return QUARTZ_DllMain(instance, reason, reserved);
37 38 39 40
}

/******************************************************************************
 * DirectShow ClassFactory
41
 */
42
typedef struct {
43
    IClassFactory IClassFactory_iface;
44
    LONG ref;
45
    HRESULT (*create_instance)(IUnknown *outer, IUnknown **out);
46 47
} IClassFactoryImpl;

48 49 50 51 52
static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface)
{
    return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface);
}

53 54 55
struct object_creation_info
{
    const CLSID *clsid;
56
    HRESULT (*create_instance)(IUnknown *outer, IUnknown **out);
57 58 59 60
};

static const struct object_creation_info object_creation[] =
{
61 62 63 64 65
    { &CLSID_ACMWrapper, acm_wrapper_create },
    { &CLSID_AsyncReader, async_reader_create },
    { &CLSID_AudioRender, dsound_render_create },
    { &CLSID_AVIDec, avi_dec_create },
    { &CLSID_DSoundRender, dsound_render_create },
66 67
    { &CLSID_FilterGraph, filter_graph_create },
    { &CLSID_FilterGraphNoThread, filter_graph_no_thread_create },
68 69 70 71 72 73 74 75 76
    { &CLSID_FilterMapper, filter_mapper_create },
    { &CLSID_FilterMapper2, filter_mapper_create },
    { &CLSID_MemoryAllocator, mem_allocator_create },
    { &CLSID_SeekingPassThru, seeking_passthrough_create },
    { &CLSID_SystemClock, system_clock_create },
    { &CLSID_VideoRenderer, video_renderer_create },
    { &CLSID_VideoMixingRenderer, vmr7_create },
    { &CLSID_VideoMixingRenderer9, vmr9_create },
    { &CLSID_VideoRendererDefault, video_renderer_default_create },
77 78
};

79
static HRESULT WINAPI DSCF_QueryInterface(IClassFactory *iface, REFIID riid, void **ppobj)
80
{
81 82 83 84
    if (IsEqualGUID(riid, &IID_IUnknown)
	|| IsEqualGUID(riid, &IID_IClassFactory))
    {
	IClassFactory_AddRef(iface);
85
        *ppobj = iface;
86 87 88
	return S_OK;
    }

89
    *ppobj = NULL;
90
    WARN("(%p)->(%s,%p), not found\n", iface, debugstr_guid(riid), ppobj);
91 92 93
    return E_NOINTERFACE;
}

94
static ULONG WINAPI DSCF_AddRef(IClassFactory *iface)
95
{
96
    IClassFactoryImpl *This = impl_from_IClassFactory(iface);
97
    return InterlockedIncrement(&This->ref);
98 99
}

100
static ULONG WINAPI DSCF_Release(IClassFactory *iface)
101
{
102
    IClassFactoryImpl *This = impl_from_IClassFactory(iface);
103
    ULONG ref = InterlockedDecrement(&This->ref);
104 105

    if (ref == 0)
106
	CoTaskMemFree(This);
107 108 109 110 111

    return ref;
}


112 113
static HRESULT WINAPI DSCF_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
                                          REFIID riid, void **ppobj)
114
{
115
    IClassFactoryImpl *This = impl_from_IClassFactory(iface);
116 117
    HRESULT hres;
    LPUNKNOWN punk;
118

119 120
    TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);

121
    *ppobj = NULL;
122 123 124
    if(pOuter && !IsEqualGUID(&IID_IUnknown, riid))
        return E_NOINTERFACE;

125 126
    if (SUCCEEDED(hres = This->create_instance(pOuter, &punk)))
    {
127 128
        hres = IUnknown_QueryInterface(punk, riid, ppobj);
        IUnknown_Release(punk);
129 130 131 132
    }
    return hres;
}

133
static HRESULT WINAPI DSCF_LockServer(IClassFactory *iface, BOOL lock)
134
{
135
    FIXME("iface %p, lock %d, stub!\n", iface, lock);
136 137 138
    return S_OK;
}

139
static const IClassFactoryVtbl DSCF_Vtbl =
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
{
    DSCF_QueryInterface,
    DSCF_AddRef,
    DSCF_Release,
    DSCF_CreateInstance,
    DSCF_LockServer
};

/*******************************************************************************
 * DllGetClassObject [QUARTZ.@]
 * Retrieves class object from a DLL object
 *
 * NOTES
 *    Docs say returns STDAPI
 *
 * PARAMS
 *    rclsid [I] CLSID for the class object
 *    riid   [I] Reference to identifier of interface for class object
 *    ppv    [O] Address of variable to receive interface pointer for riid
 *
 * RETURNS
 *    Success: S_OK
 *    Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
 *             E_UNEXPECTED
 */
165
HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
166
{
167
    unsigned int i;
168

169
    TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
170

171
    if (IsEqualGUID( &IID_IClassFactory, riid ) || IsEqualGUID( &IID_IUnknown, riid))
172
    {
173
        for (i = 0; i < ARRAY_SIZE(object_creation); i++)
174 175 176 177 178 179
        {
            if (IsEqualGUID(object_creation[i].clsid, rclsid))
            {
                IClassFactoryImpl *factory = CoTaskMemAlloc(sizeof(*factory));
                if (factory == NULL) return E_OUTOFMEMORY;

180
                factory->IClassFactory_iface.lpVtbl = &DSCF_Vtbl;
181 182
                factory->ref = 1;

183
                factory->create_instance = object_creation[i].create_instance;
184

185
                *ppv = &factory->IClassFactory_iface;
186 187 188
                return S_OK;
            }
        }
189
    }
190
    return QUARTZ_DllGetClassObject( rclsid, riid, ppv );
191 192
}

193 194 195
#define OUR_GUID_ENTRY(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
    { { l, w1, w2, { b1, b2,  b3,  b4,  b5,  b6,  b7,  b8 } } , #name },

196
static const struct {
197
	const GUID	riid;
198
	const char 	*name;
199 200
} InterfaceDesc[] =
{
201 202
#include "uuids.h"
    { { 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0} }, NULL }
203 204
};

205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
/***********************************************************************
 *              proxies
 */
HRESULT CALLBACK ICaptureGraphBuilder_FindInterface_Proxy( ICaptureGraphBuilder *This,
                                                           const GUID *pCategory,
                                                           IBaseFilter *pf,
                                                           REFIID riid,
                                                           void **ppint )
{
    return ICaptureGraphBuilder_RemoteFindInterface_Proxy( This, pCategory, pf,
                                                           riid, (IUnknown **)ppint );
}

HRESULT __RPC_STUB ICaptureGraphBuilder_FindInterface_Stub( ICaptureGraphBuilder *This,
                                                            const GUID *pCategory,
                                                            IBaseFilter *pf,
                                                            REFIID riid,
                                                            IUnknown **ppint )
{
    return ICaptureGraphBuilder_FindInterface( This, pCategory, pf, riid, (void **)ppint );
}

HRESULT CALLBACK ICaptureGraphBuilder2_FindInterface_Proxy( ICaptureGraphBuilder2 *This,
                                                            const GUID *pCategory,
                                                            const GUID *pType,
                                                            IBaseFilter *pf,
                                                            REFIID riid,
                                                            void **ppint )
{
    return ICaptureGraphBuilder2_RemoteFindInterface_Proxy( This, pCategory, pType,
                                                            pf, riid, (IUnknown **)ppint );
}

HRESULT __RPC_STUB ICaptureGraphBuilder2_FindInterface_Stub( ICaptureGraphBuilder2 *This,
                                                             const GUID *pCategory,
                                                             const GUID *pType,
                                                             IBaseFilter *pf,
                                                             REFIID riid,
                                                             IUnknown **ppint )
{
    return ICaptureGraphBuilder2_FindInterface( This, pCategory, pType, pf, riid, (void **)ppint );
}

248 249 250 251 252 253 254 255 256
/***********************************************************************
 *              qzdebugstr_guid (internal)
 *
 * Gives a text version of DirectShow GUIDs
 */
const char * qzdebugstr_guid( const GUID * id )
{
    int i;

257
    for (i=0; InterfaceDesc[i].name; i++)
258
        if (IsEqualGUID(&InterfaceDesc[i].riid, id)) return InterfaceDesc[i].name;
259

260 261 262
    return debugstr_guid(id);
}

263
int WINAPI AmpFactorToDB(int ampfactor)
264
{
265
    FIXME("(%d) Stub!\n", ampfactor);
266 267 268
    return 0;
}

269
int WINAPI DBToAmpFactor(int db)
270
{
271
    FIXME("(%d) Stub!\n", db);
272 273 274 275 276
    /* Avoid divide by zero (probably during range computation) in Windows Media Player 6.4 */
    if (db < -1000)
	return 0;
    return 100;
}
277

278 279 280
/***********************************************************************
 *              AMGetErrorTextA (QUARTZ.@)
 */
281
DWORD WINAPI AMGetErrorTextA(HRESULT hr, LPSTR buffer, DWORD maxlen)
282
{
283 284
    DWORD res;
    WCHAR errorW[MAX_ERROR_TEXT_LEN];
285

286 287
    TRACE("hr %#lx, buffer %p, maxlen %lu.\n", hr, buffer, maxlen);

288 289
    if (!buffer)
        return 0;
290

291
    res = AMGetErrorTextW(hr, errorW, ARRAY_SIZE(errorW));
292 293 294 295 296 297 298
    if (!res)
        return 0;

    res = WideCharToMultiByte(CP_ACP, 0, errorW, -1, NULL, 0, 0, 0);
    if (res > maxlen || !res)
        return 0;
    return WideCharToMultiByte(CP_ACP, 0, errorW, -1, buffer, maxlen, 0, 0) - 1;
299 300
}

301 302 303
/***********************************************************************
 *              AMGetErrorTextW (QUARTZ.@)
 */
304
DWORD WINAPI AMGetErrorTextW(HRESULT hr, LPWSTR buffer, DWORD maxlen)
305
{
306
    unsigned int len;
307 308
    WCHAR error[MAX_ERROR_TEXT_LEN];

309
    TRACE("hr %#lx, buffer %p, maxlen %lu.\n", hr, buffer, maxlen);
310 311

    if (!buffer) return 0;
312 313 314 315
    swprintf(error, ARRAY_SIZE(error), L"Error: 0x%lx", hr);
    if ((len = wcslen(error)) >= maxlen)
        return 0;
    wcscpy(buffer, error);
316 317
    return len;
}