winegstreamer: Fix deadlock when changing state.
[wine] / dlls / winegstreamer / main.c
1 /* Gstreamer Base Functions
2  *
3  * Copyright 2002 Lionel Ulmer
4  * Copyright 2010 Aric Stewart, CodeWeavers
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "config.h"
22 #include <stdarg.h>
23 #include <stdio.h>
24
25 #include <gst/app/gstappsink.h>
26 #include <gst/app/gstappsrc.h>
27 #include <gst/app/gstappbuffer.h>
28
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winuser.h"
32 #include "winreg.h"
33 #include "winerror.h"
34 #include "advpub.h"
35 #include "wine/debug.h"
36
37 #include "wine/unicode.h"
38 #include "gst_private.h"
39 #include "initguid.h"
40 #include "gst_guids.h"
41
42 static HINSTANCE hInst = NULL;
43
44 WINE_DEFAULT_DEBUG_CHANNEL(gstreamer);
45
46 static const WCHAR wGstreamer_Splitter[] =
47 {'G','S','t','r','e','a','m','e','r',' ','s','p','l','i','t','t','e','r',' ','f','i','l','t','e','r',0};
48 static const WCHAR wGstreamer_YUV[] =
49 {'G','S','t','r','e','a','m','e','r',' ','Y','U','V',' ','f','i','l','t','e','r',0};
50 static const WCHAR wGstreamer_Mp3[] =
51 {'G','S','t','r','e','a','m','e','r',' ','M','p','3',' ','f','i','l','t','e','r',0};
52 static const WCHAR wGstreamer_AudioConvert[] =
53 {'G','S','t','r','e','a','m','e','r',' ','A','u','d','i','o','C','o','n','v','e','r','t',' ','f','i','l','t','e','r',0};
54
55 static WCHAR wNull[] = {'\0'};
56
57 static const AMOVIESETUP_MEDIATYPE amfMTstream[] =
58 {   { &MEDIATYPE_Stream, &WINESUBTYPE_Gstreamer },
59     { &MEDIATYPE_Stream, &MEDIASUBTYPE_NULL },
60 };
61
62 static const AMOVIESETUP_MEDIATYPE amfMTaudio[] =
63 {   { &MEDIATYPE_Audio, &MEDIASUBTYPE_NULL } };
64
65 static const AMOVIESETUP_MEDIATYPE amfMTvideo[] =
66 {   { &MEDIATYPE_Video, &MEDIASUBTYPE_NULL } };
67
68 static const AMOVIESETUP_PIN amfSplitPin[] =
69 {   {   wNull,
70         FALSE, FALSE, FALSE, FALSE,
71         &GUID_NULL,
72         NULL,
73         2,
74         amfMTstream
75     },
76     {
77         wNull,
78         FALSE, TRUE, FALSE, FALSE,
79         &GUID_NULL,
80         NULL,
81         1,
82         amfMTaudio
83     },
84     {
85         wNull,
86         FALSE, TRUE, FALSE, FALSE,
87         &GUID_NULL,
88         NULL,
89         1,
90         amfMTvideo
91     }
92 };
93
94 static const AMOVIESETUP_FILTER amfSplitter =
95 {   &CLSID_Gstreamer_Splitter,
96     wGstreamer_Splitter,
97     MERIT_PREFERRED,
98     3,
99     amfSplitPin
100 };
101
102 static const AMOVIESETUP_PIN amfYUVPin[] =
103 {   {   wNull,
104         FALSE, FALSE, FALSE, FALSE,
105         &GUID_NULL,
106         NULL,
107         1,
108         amfMTvideo
109     },
110     {
111         wNull,
112         FALSE, TRUE, FALSE, FALSE,
113         &GUID_NULL,
114         NULL,
115         1,
116         amfMTvideo
117     },
118 };
119
120 static const AMOVIESETUP_FILTER amfYUV =
121 {   &CLSID_Gstreamer_YUV,
122     wGstreamer_YUV,
123     MERIT_UNLIKELY,
124     2,
125     amfYUVPin
126 };
127
128 AMOVIESETUP_PIN amfMp3Pin[] =
129 {   {   wNull,
130         FALSE, FALSE, FALSE, FALSE,
131         &GUID_NULL,
132         NULL,
133         1,
134         amfMTaudio
135     },
136     {
137         wNull,
138         FALSE, TRUE, FALSE, FALSE,
139         &GUID_NULL,
140         NULL,
141         1,
142         amfMTaudio
143     },
144 };
145
146 AMOVIESETUP_FILTER const amfMp3 =
147 {   &CLSID_Gstreamer_Mp3,
148     wGstreamer_Mp3,
149     MERIT_NORMAL,
150     2,
151     amfMp3Pin
152 };
153
154 AMOVIESETUP_PIN amfAudioConvertPin[] =
155 {   {   wNull,
156         FALSE, FALSE, FALSE, FALSE,
157         &GUID_NULL,
158         NULL,
159         1,
160         amfMTaudio
161     },
162     {
163         wNull,
164         FALSE, TRUE, FALSE, FALSE,
165         &GUID_NULL,
166         NULL,
167         1,
168         amfMTaudio
169     },
170 };
171
172 AMOVIESETUP_FILTER const amfAudioConvert =
173 {   &CLSID_Gstreamer_AudioConvert,
174     wGstreamer_AudioConvert,
175     MERIT_UNLIKELY,
176     2,
177     amfAudioConvertPin
178 };
179
180 FactoryTemplate const g_Templates[] = {
181     {
182         wGstreamer_Splitter,
183         &CLSID_Gstreamer_Splitter,
184         Gstreamer_Splitter_create,
185         NULL,
186         &amfSplitter,
187     },
188     {
189         wGstreamer_YUV,
190         &CLSID_Gstreamer_YUV,
191         Gstreamer_YUV_create,
192         NULL,
193         &amfYUV,
194     },
195     {
196         wGstreamer_Mp3,
197         &CLSID_Gstreamer_Mp3,
198         Gstreamer_Mp3_create,
199         NULL,
200         &amfMp3,
201     },
202     {
203         wGstreamer_AudioConvert,
204         &CLSID_Gstreamer_AudioConvert,
205         Gstreamer_AudioConvert_create,
206         NULL,
207         &amfAudioConvert,
208     },
209 };
210
211 const int g_cTemplates = sizeof(g_Templates) / sizeof (g_Templates[0]);
212
213 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
214 {
215     if (fdwReason == DLL_PROCESS_ATTACH)
216         hInst = hInstDLL;
217     return STRMBASE_DllMain(hInstDLL, fdwReason, lpv);
218 }
219
220 /***********************************************************************
221  *    DllCanUnloadNow
222  */
223 HRESULT WINAPI DllCanUnloadNow(void)
224 {
225     return STRMBASE_DllCanUnloadNow();
226 }
227
228 /***********************************************************************
229  *    DllGetClassObject
230  */
231 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
232 {
233     return STRMBASE_DllGetClassObject( rclsid, riid, ppv );
234 }
235
236 /* GStreamer common functions */
237
238 void dump_AM_MEDIA_TYPE(const AM_MEDIA_TYPE * pmt)
239 {
240     if (!pmt)
241         return;
242     TRACE("\t%s\n\t%s\n\t...\n\t%s\n", debugstr_guid(&pmt->majortype), debugstr_guid(&pmt->subtype), debugstr_guid(&pmt->formattype));
243 }
244
245 DWORD Gstreamer_init(void) {
246     static int inited;
247
248     if (!inited) {
249         char argv0[] = "wine";
250         char argv1[] = "--gst-disable-registry-fork";
251         char **argv = HeapAlloc(GetProcessHeap(), 0, sizeof(char *)*3);
252         int argc = 2;
253         GError *err = NULL;
254         argv[0] = argv0;
255         argv[1] = argv1;
256         argv[2] = NULL;
257         g_thread_impl_init();
258         inited = gst_init_check(&argc, &argv, &err);
259         HeapFree(GetProcessHeap(), 0, argv);
260         if (err) {
261             FIXME("Failed to initialize gstreamer: %s\n", err->message);
262             g_error_free(err);
263         }
264     }
265     return inited;
266 }
267
268 #define INF_SET_ID(id)            \
269     do                            \
270     {                             \
271         static CHAR name[] = #id; \
272                                   \
273         pse[i].pszName = name;    \
274         clsids[i++] = &id;        \
275     } while (0)
276
277 #define INF_SET_CLSID(clsid) INF_SET_ID(CLSID_ ## clsid)
278
279 static HRESULT register_server(BOOL do_register)
280 {
281     HRESULT hres;
282     HMODULE hAdvpack;
283     HRESULT (WINAPI *pRegInstall)(HMODULE hm, LPCSTR pszSection, const STRTABLEA* pstTable);
284     STRTABLEA strtable;
285     STRENTRYA pse[3];
286     static CLSID const *clsids[3];
287     unsigned int i = 0;
288
289     static const WCHAR wszAdvpack[] = {'a','d','v','p','a','c','k','.','d','l','l',0};
290
291     TRACE("(%x)\n", do_register);
292
293     INF_SET_CLSID(AsyncReader);
294     INF_SET_ID(MEDIATYPE_Stream);
295     INF_SET_ID(WINESUBTYPE_Gstreamer);
296
297     for(i=0; i < sizeof(pse)/sizeof(pse[0]); i++) {
298         pse[i].pszValue = HeapAlloc(GetProcessHeap(),0,39);
299         sprintf(pse[i].pszValue, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
300                 clsids[i]->Data1, clsids[i]->Data2, clsids[i]->Data3, clsids[i]->Data4[0],
301                 clsids[i]->Data4[1], clsids[i]->Data4[2], clsids[i]->Data4[3], clsids[i]->Data4[4],
302                 clsids[i]->Data4[5], clsids[i]->Data4[6], clsids[i]->Data4[7]);
303     }
304
305     strtable.cEntries = sizeof(pse)/sizeof(pse[0]);
306     strtable.pse = pse;
307
308     hAdvpack = LoadLibraryW(wszAdvpack);
309     pRegInstall = (void *)GetProcAddress(hAdvpack, "RegInstall");
310
311     hres = pRegInstall(hInst, do_register ? "RegisterDll" : "UnregisterDll", &strtable);
312
313     for(i=0; i < sizeof(pse)/sizeof(pse[0]); i++)
314         HeapFree(GetProcessHeap(),0,pse[i].pszValue);
315
316     if(FAILED(hres)) {
317         ERR("RegInstall failed: %08x\n", hres);
318         return hres;
319     }
320
321     return hres;
322 }
323
324 #undef INF_SET_CLSID
325 #undef INF_SET_ID
326
327 /***********************************************************************
328  *      DllRegisterServer
329  */
330 HRESULT WINAPI DllRegisterServer(void)
331 {
332     HRESULT hr;
333
334     TRACE("\n");
335
336     hr = AMovieDllRegisterServer2(TRUE);
337     if (SUCCEEDED(hr))
338         hr = register_server(TRUE);
339     return hr;
340 }
341
342 /***********************************************************************
343  *      DllUnregisterServer
344  */
345 HRESULT WINAPI DllUnregisterServer(void)
346 {
347     HRESULT hr;
348
349     TRACE("\n");
350
351     hr = AMovieDllRegisterServer2(FALSE);
352     if (SUCCEEDED(hr))
353         hr = register_server(FALSE);
354     return hr;
355 }