kernel32: Return a non-empty username from GetNamedPipeHandleState.
[wine.git] / dlls / winegstreamer / gst_cbs.c
blobc8ba812c8a70e0a4290e992cfd4026c0d18112fc
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 GstFlowReturn got_data_sink_wrapper(GstPad *pad, GstObject *parent, GstBuffer *buf)
180 struct cb_data cbdata = { GOT_DATA_SINK };
182 cbdata.u.got_data_sink_data.pad = pad;
183 cbdata.u.got_data_sink_data.parent = parent;
184 cbdata.u.got_data_sink_data.buf = buf;
186 call_cb(&cbdata);
188 return cbdata.u.got_data_sink_data.ret;
191 GstFlowReturn got_data_wrapper(GstPad *pad, GstObject *parent, GstBuffer *buf)
193 struct cb_data cbdata = { GOT_DATA };
195 cbdata.u.got_data_data.pad = pad;
196 cbdata.u.got_data_data.parent = parent;
197 cbdata.u.got_data_data.buf = buf;
199 call_cb(&cbdata);
201 return cbdata.u.got_data_data.ret;
204 void removed_decoded_pad_wrapper(GstElement *bin, GstPad *pad, gpointer user)
206 struct cb_data cbdata = { REMOVED_DECODED_PAD };
208 cbdata.u.removed_decoded_pad_data.bin = bin;
209 cbdata.u.removed_decoded_pad_data.pad = pad;
210 cbdata.u.removed_decoded_pad_data.user = user;
212 call_cb(&cbdata);
215 GstAutoplugSelectResult autoplug_blacklist_wrapper(GstElement *bin, GstPad *pad,
216 GstCaps *caps, GstElementFactory *fact, gpointer user)
218 struct cb_data cbdata = { AUTOPLUG_BLACKLIST };
220 cbdata.u.autoplug_blacklist_data.bin = bin;
221 cbdata.u.autoplug_blacklist_data.pad = pad;
222 cbdata.u.autoplug_blacklist_data.caps = caps;
223 cbdata.u.autoplug_blacklist_data.fact = fact;
224 cbdata.u.autoplug_blacklist_data.user = user;
226 call_cb(&cbdata);
228 return cbdata.u.autoplug_blacklist_data.ret;
231 void unknown_type_wrapper(GstElement *bin, GstPad *pad, GstCaps *caps, gpointer user)
233 struct cb_data cbdata = { UNKNOWN_TYPE };
235 cbdata.u.unknown_type_data.bin = bin;
236 cbdata.u.unknown_type_data.pad = pad;
237 cbdata.u.unknown_type_data.caps = caps;
238 cbdata.u.unknown_type_data.user = user;
240 call_cb(&cbdata);
243 void release_sample_wrapper(gpointer data)
245 struct cb_data cbdata = { RELEASE_SAMPLE };
247 cbdata.u.release_sample_data.data = data;
249 call_cb(&cbdata);
252 void Gstreamer_transform_pad_added_wrapper(GstElement *filter, GstPad *pad, gpointer user)
254 struct cb_data cbdata = { TRANSFORM_PAD_ADDED };
256 cbdata.u.transform_pad_added_data.filter = filter;
257 cbdata.u.transform_pad_added_data.pad = pad;
258 cbdata.u.transform_pad_added_data.user = user;
260 call_cb(&cbdata);
263 gboolean query_sink_wrapper(GstPad *pad, GstObject *parent, GstQuery *query)
265 struct cb_data cbdata = { QUERY_SINK };
267 cbdata.u.query_sink_data.pad = pad;
268 cbdata.u.query_sink_data.parent = parent;
269 cbdata.u.query_sink_data.query = query;
271 call_cb(&cbdata);
273 return cbdata.u.query_sink_data.ret;