user32/tests: Show that message conversion should work on window procedures without...
[wine.git] / dlls / winegstreamer / gst_cbs.c
blob96325d042f46663e6857be51eff67c038b282e8b
1 /*
2 * Copyright 2015 Andrew Eikum for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include "config.h"
21 #include <gst/gst.h>
23 #include "wine/list.h"
25 #include "gst_cbs.h"
27 /* gstreamer calls our callbacks from threads that Wine did not create. Some
28 * callbacks execute code which requires Wine to have created the thread
29 * (critical sections, debug logging, dshow client code). Since gstreamer can't
30 * provide an API to override its thread creation, we have to intercept all
31 * callbacks in code which avoids the Wine thread requirement, and then
32 * dispatch those callbacks on a thread that is known to be created by Wine.
34 * This file must not contain any code that depends on the Wine TEB!
37 static void call_cb(struct cb_data *cbdata)
39 pthread_mutex_init(&cbdata->lock, NULL);
40 pthread_cond_init(&cbdata->cond, NULL);
41 cbdata->finished = 0;
43 if(is_wine_thread()){
44 /* The thread which triggered gstreamer to call this callback may
45 * already hold a critical section. If so, executing the callback on a
46 * worker thread can cause a deadlock. If we are already on a Wine
47 * thread, then there is no need to run this callback on a worker
48 * thread anyway, which avoids the deadlock issue. */
49 perform_cb(NULL, cbdata);
51 pthread_cond_destroy(&cbdata->cond);
52 pthread_mutex_destroy(&cbdata->lock);
54 return;
57 pthread_mutex_lock(&cb_list_lock);
59 list_add_tail(&cb_list, &cbdata->entry);
60 pthread_cond_broadcast(&cb_list_cond);
62 pthread_mutex_lock(&cbdata->lock);
64 pthread_mutex_unlock(&cb_list_lock);
66 while(!cbdata->finished)
67 pthread_cond_wait(&cbdata->cond, &cbdata->lock);
69 pthread_mutex_unlock(&cbdata->lock);
71 pthread_cond_destroy(&cbdata->cond);
72 pthread_mutex_destroy(&cbdata->lock);
75 GstBusSyncReply watch_bus_wrapper(GstBus *bus, GstMessage *msg, gpointer user)
77 struct cb_data cbdata = { WATCH_BUS };
79 cbdata.u.watch_bus_data.bus = bus;
80 cbdata.u.watch_bus_data.msg = msg;
81 cbdata.u.watch_bus_data.user = user;
83 call_cb(&cbdata);
85 return cbdata.u.watch_bus_data.ret;
88 void existing_new_pad_wrapper(GstElement *bin, GstPad *pad, gpointer user)
90 struct cb_data cbdata = { EXISTING_NEW_PAD };
92 cbdata.u.existing_new_pad_data.bin = bin;
93 cbdata.u.existing_new_pad_data.pad = pad;
94 cbdata.u.existing_new_pad_data.user = user;
96 call_cb(&cbdata);
99 gboolean query_function_wrapper(GstPad *pad, GstObject *parent, GstQuery *query)
101 struct cb_data cbdata = { QUERY_FUNCTION };
103 cbdata.u.query_function_data.pad = pad;
104 cbdata.u.query_function_data.parent = parent;
105 cbdata.u.query_function_data.query = query;
107 call_cb(&cbdata);
109 return cbdata.u.query_function_data.ret;
112 gboolean activate_mode_wrapper(GstPad *pad, GstObject *parent, GstPadMode mode, gboolean activate)
114 struct cb_data cbdata = { ACTIVATE_MODE };
116 cbdata.u.activate_mode_data.pad = pad;
117 cbdata.u.activate_mode_data.parent = parent;
118 cbdata.u.activate_mode_data.mode = mode;
119 cbdata.u.activate_mode_data.activate = activate;
121 call_cb(&cbdata);
123 return cbdata.u.activate_mode_data.ret;
126 void no_more_pads_wrapper(GstElement *decodebin, gpointer user)
128 struct cb_data cbdata = { NO_MORE_PADS };
130 cbdata.u.no_more_pads_data.decodebin = decodebin;
131 cbdata.u.no_more_pads_data.user = user;
133 call_cb(&cbdata);
136 GstFlowReturn request_buffer_src_wrapper(GstPad *pad, GstObject *parent, guint64 ofs, guint len,
137 GstBuffer **buf)
139 struct cb_data cbdata = { REQUEST_BUFFER_SRC };
141 cbdata.u.request_buffer_src_data.pad = pad;
142 cbdata.u.request_buffer_src_data.parent = parent;
143 cbdata.u.request_buffer_src_data.ofs = ofs;
144 cbdata.u.request_buffer_src_data.len = len;
145 cbdata.u.request_buffer_src_data.buf = buf;
147 call_cb(&cbdata);
149 return cbdata.u.request_buffer_src_data.ret;
152 gboolean event_src_wrapper(GstPad *pad, GstObject *parent, GstEvent *event)
154 struct cb_data cbdata = { EVENT_SRC };
156 cbdata.u.event_src_data.pad = pad;
157 cbdata.u.event_src_data.parent = parent;
158 cbdata.u.event_src_data.event = event;
160 call_cb(&cbdata);
162 return cbdata.u.event_src_data.ret;
165 gboolean event_sink_wrapper(GstPad *pad, GstObject *parent, GstEvent *event)
167 struct cb_data cbdata = { EVENT_SINK };
169 cbdata.u.event_sink_data.pad = pad;
170 cbdata.u.event_sink_data.parent = parent;
171 cbdata.u.event_sink_data.event = event;
173 call_cb(&cbdata);
175 return cbdata.u.event_sink_data.ret;
178 gboolean accept_caps_sink_wrapper(GstPad *pad, GstCaps *caps)
180 struct cb_data cbdata = { ACCEPT_CAPS_SINK };
182 cbdata.u.accept_caps_sink_data.pad = pad;
183 cbdata.u.accept_caps_sink_data.caps = caps;
185 call_cb(&cbdata);
187 return cbdata.u.accept_caps_sink_data.ret;
190 gboolean setcaps_sink_wrapper(GstPad *pad, GstCaps *caps)
192 struct cb_data cbdata = { SETCAPS_SINK };
194 cbdata.u.setcaps_sink_data.pad = pad;
195 cbdata.u.setcaps_sink_data.caps = caps;
197 call_cb(&cbdata);
199 return cbdata.u.setcaps_sink_data.ret;
202 GstFlowReturn got_data_sink_wrapper(GstPad *pad, GstObject *parent, GstBuffer *buf)
204 struct cb_data cbdata = { GOT_DATA_SINK };
206 cbdata.u.got_data_sink_data.pad = pad;
207 cbdata.u.got_data_sink_data.parent = parent;
208 cbdata.u.got_data_sink_data.buf = buf;
210 call_cb(&cbdata);
212 return cbdata.u.got_data_sink_data.ret;
215 GstFlowReturn got_data_wrapper(GstPad *pad, GstObject *parent, GstBuffer *buf)
217 struct cb_data cbdata = { GOT_DATA };
219 cbdata.u.got_data_data.pad = pad;
220 cbdata.u.got_data_data.parent = parent;
221 cbdata.u.got_data_data.buf = buf;
223 call_cb(&cbdata);
225 return cbdata.u.got_data_data.ret;
228 void removed_decoded_pad_wrapper(GstElement *bin, GstPad *pad, gpointer user)
230 struct cb_data cbdata = { REMOVED_DECODED_PAD };
232 cbdata.u.removed_decoded_pad_data.bin = bin;
233 cbdata.u.removed_decoded_pad_data.pad = pad;
234 cbdata.u.removed_decoded_pad_data.user = user;
236 call_cb(&cbdata);
239 GstAutoplugSelectResult autoplug_blacklist_wrapper(GstElement *bin, GstPad *pad,
240 GstCaps *caps, GstElementFactory *fact, gpointer user)
242 struct cb_data cbdata = { AUTOPLUG_BLACKLIST };
244 cbdata.u.autoplug_blacklist_data.bin = bin;
245 cbdata.u.autoplug_blacklist_data.pad = pad;
246 cbdata.u.autoplug_blacklist_data.caps = caps;
247 cbdata.u.autoplug_blacklist_data.fact = fact;
248 cbdata.u.autoplug_blacklist_data.user = user;
250 call_cb(&cbdata);
252 return cbdata.u.autoplug_blacklist_data.ret;
255 void unknown_type_wrapper(GstElement *bin, GstPad *pad, GstCaps *caps, gpointer user)
257 struct cb_data cbdata = { UNKNOWN_TYPE };
259 cbdata.u.unknown_type_data.bin = bin;
260 cbdata.u.unknown_type_data.pad = pad;
261 cbdata.u.unknown_type_data.caps = caps;
262 cbdata.u.unknown_type_data.user = user;
264 call_cb(&cbdata);
267 void release_sample_wrapper(gpointer data)
269 struct cb_data cbdata = { RELEASE_SAMPLE };
271 cbdata.u.release_sample_data.data = data;
273 call_cb(&cbdata);
276 void Gstreamer_transform_pad_added_wrapper(GstElement *filter, GstPad *pad, gpointer user)
278 struct cb_data cbdata = { TRANSFORM_PAD_ADDED };
280 cbdata.u.transform_pad_added_data.filter = filter;
281 cbdata.u.transform_pad_added_data.pad = pad;
282 cbdata.u.transform_pad_added_data.user = user;
284 call_cb(&cbdata);
287 gboolean query_sink_wrapper(GstPad *pad, GstObject *parent, GstQuery *query)
289 struct cb_data cbdata = { QUERY_SINK };
291 cbdata.u.query_sink_data.pad = pad;
292 cbdata.u.query_sink_data.parent = parent;
293 cbdata.u.query_sink_data.query = query;
295 call_cb(&cbdata);
297 return cbdata.u.query_sink_data.ret;