|
1 /* GStreamer X-based Overlay |
|
2 * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net> |
|
3 * |
|
4 * x-overlay.c: X-based overlay interface design |
|
5 * |
|
6 * This library is free software; you can redistribute it and/or |
|
7 * modify it under the terms of the GNU Library General Public |
|
8 * License as published by the Free Software Foundation; either |
|
9 * version 2 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 * Library General Public License for more details. |
|
15 * |
|
16 * You should have received a copy of the GNU Library General Public |
|
17 * License along with this library; if not, write to the |
|
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
|
19 * Boston, MA 02111-1307, USA. |
|
20 */ |
|
21 |
|
22 /** |
|
23 * SECTION:gstxoverlay |
|
24 * @short_description: Interface for setting/getting a Window on elements |
|
25 * supporting it |
|
26 * |
|
27 * <refsect2> |
|
28 * <para> |
|
29 * The XOverlay interface is used for 2 main purposes : |
|
30 * <itemizedlist> |
|
31 * <listitem> |
|
32 * <para> |
|
33 * To get a grab on the Window where the video sink element is going to render. |
|
34 * This is achieved by either being informed about the Window identifier that |
|
35 * the video sink element generated, or by forcing the video sink element to use |
|
36 * a specific Window identifier for rendering. |
|
37 * </para> |
|
38 * </listitem> |
|
39 * <listitem> |
|
40 * <para> |
|
41 * To force a redrawing of the latest video frame the video sink element |
|
42 * displayed on the Window. Indeed if the #GstPipeline is in #GST_STATE_PAUSED |
|
43 * state, moving the Window around will damage its content. Application |
|
44 * developers will want to handle the Expose events themselves and force the |
|
45 * video sink element to refresh the Window's content. |
|
46 * </para> |
|
47 * </listitem> |
|
48 * </itemizedlist> |
|
49 * </para> |
|
50 * <para> |
|
51 * Using the Window created by the video sink is probably the simplest scenario, |
|
52 * in some cases, though, it might not be flexible enough for application |
|
53 * developers if they need to catch events such as mouse moves and button |
|
54 * clicks. |
|
55 * </para> |
|
56 * <para> |
|
57 * Setting a specific Window identifier on the video sink element is the most |
|
58 * flexible solution but it has some issues. Indeed the application needs to set |
|
59 * its Window identifier at the right time to avoid internal Window creation |
|
60 * from the video sink element. To solve this issue a #GstMessage is posted on |
|
61 * the bus to inform the application that it should set the Window identifier |
|
62 * immediately. Here is an example on how to do that correctly: |
|
63 * <programlisting> |
|
64 * static GstBusSyncReply |
|
65 * create_window (GstBus * bus, GstMessage * message, GstPipeline * pipeline) |
|
66 * { |
|
67 * // ignore anything but 'prepare-xwindow-id' element messages |
|
68 * if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT) |
|
69 * return GST_BUS_PASS; |
|
70 * |
|
71 * if (!gst_structure_has_name (message->structure, "prepare-xwindow-id")) |
|
72 * return GST_BUS_PASS; |
|
73 * |
|
74 * win = XCreateSimpleWindow (disp, root, 0, 0, 320, 240, 0, 0, 0); |
|
75 * |
|
76 * XSetWindowBackgroundPixmap (disp, win, None); |
|
77 * |
|
78 * XMapRaised (disp, win); |
|
79 * |
|
80 * XSync (disp, FALSE); |
|
81 * |
|
82 * gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (GST_MESSAGE_SRC (message)), |
|
83 * win); |
|
84 * |
|
85 * gst_message_unref (message); |
|
86 * |
|
87 * return GST_BUS_DROP; |
|
88 * } |
|
89 * ... |
|
90 * int |
|
91 * main (int argc, char **argv) |
|
92 * { |
|
93 * ... |
|
94 * bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); |
|
95 * gst_bus_set_sync_handler (bus, (GstBusSyncHandler) create_window, pipeline); |
|
96 * ... |
|
97 * } |
|
98 * </programlisting> |
|
99 * </para> |
|
100 * </refsect2> |
|
101 */ |
|
102 |
|
103 #ifdef HAVE_CONFIG_H |
|
104 #include "config.h" |
|
105 #endif |
|
106 |
|
107 #include "xoverlay.h" |
|
108 |
|
109 static void gst_x_overlay_base_init (gpointer g_class); |
|
110 #ifdef __SYMBIAN32__ |
|
111 EXPORT_C |
|
112 #endif |
|
113 |
|
114 |
|
115 GType |
|
116 gst_x_overlay_get_type (void) |
|
117 { |
|
118 static GType gst_x_overlay_type = 0; |
|
119 |
|
120 if (!gst_x_overlay_type) { |
|
121 static const GTypeInfo gst_x_overlay_info = { |
|
122 sizeof (GstXOverlayClass), |
|
123 gst_x_overlay_base_init, |
|
124 NULL, |
|
125 NULL, |
|
126 NULL, |
|
127 NULL, |
|
128 0, |
|
129 0, |
|
130 NULL, |
|
131 }; |
|
132 |
|
133 gst_x_overlay_type = g_type_register_static (G_TYPE_INTERFACE, |
|
134 "GstXOverlay", &gst_x_overlay_info, 0); |
|
135 g_type_interface_add_prerequisite (gst_x_overlay_type, |
|
136 GST_TYPE_IMPLEMENTS_INTERFACE); |
|
137 } |
|
138 |
|
139 return gst_x_overlay_type; |
|
140 } |
|
141 |
|
142 static void |
|
143 gst_x_overlay_base_init (gpointer g_class) |
|
144 { |
|
145 GstXOverlayClass *overlay_class = (GstXOverlayClass *) g_class; |
|
146 |
|
147 overlay_class->set_xwindow_id = NULL; |
|
148 } |
|
149 |
|
150 /** |
|
151 * gst_x_overlay_set_xwindow_id: |
|
152 * @overlay: a #GstXOverlay to set the XWindow on. |
|
153 * @xwindow_id: a #XID referencing the XWindow. |
|
154 * |
|
155 * This will call the video overlay's set_xwindow_id method. You should |
|
156 * use this method to tell to a XOverlay to display video output to a |
|
157 * specific XWindow. Passing 0 as the xwindow_id will tell the overlay to |
|
158 * stop using that window and create an internal one. |
|
159 */ |
|
160 #ifdef __SYMBIAN32__ |
|
161 EXPORT_C |
|
162 #endif |
|
163 |
|
164 void |
|
165 gst_x_overlay_set_xwindow_id (GstXOverlay * overlay, gulong xwindow_id) |
|
166 { |
|
167 GstXOverlayClass *klass; |
|
168 |
|
169 g_return_if_fail (overlay != NULL); |
|
170 g_return_if_fail (GST_IS_X_OVERLAY (overlay)); |
|
171 |
|
172 klass = GST_X_OVERLAY_GET_CLASS (overlay); |
|
173 |
|
174 if (klass->set_xwindow_id) { |
|
175 klass->set_xwindow_id (overlay, xwindow_id); |
|
176 } |
|
177 } |
|
178 |
|
179 /** |
|
180 * gst_x_overlay_got_xwindow_id: |
|
181 * @overlay: a #GstXOverlay which got a XWindow. |
|
182 * @xwindow_id: a #XID referencing the XWindow. |
|
183 * |
|
184 * This will post a "have-xwindow-id" element message on the bus. |
|
185 * |
|
186 * This function should only be used by video overlay plugin developers. |
|
187 */ |
|
188 #ifdef __SYMBIAN32__ |
|
189 EXPORT_C |
|
190 #endif |
|
191 |
|
192 void |
|
193 gst_x_overlay_got_xwindow_id (GstXOverlay * overlay, gulong xwindow_id) |
|
194 { |
|
195 GstStructure *s; |
|
196 GstMessage *msg; |
|
197 |
|
198 g_return_if_fail (overlay != NULL); |
|
199 g_return_if_fail (GST_IS_X_OVERLAY (overlay)); |
|
200 |
|
201 GST_LOG_OBJECT (GST_OBJECT (overlay), "xwindow_id = %lu", xwindow_id); |
|
202 s = gst_structure_new ("have-xwindow-id", "xwindow-id", G_TYPE_ULONG, |
|
203 xwindow_id, NULL); |
|
204 msg = gst_message_new_element (GST_OBJECT (overlay), s); |
|
205 gst_element_post_message (GST_ELEMENT (overlay), msg); |
|
206 } |
|
207 |
|
208 /** |
|
209 * gst_x_overlay_prepare_xwindow_id: |
|
210 * @overlay: a #GstXOverlay which does not yet have an XWindow. |
|
211 * |
|
212 * This will post a "prepare-xwindow-id" element message on the bus |
|
213 * to give applications an opportunity to call |
|
214 * gst_x_overlay_set_xwindow_id() before a plugin creates its own |
|
215 * window. |
|
216 * |
|
217 * This function should only be used by video overlay plugin developers. |
|
218 */ |
|
219 #ifdef __SYMBIAN32__ |
|
220 EXPORT_C |
|
221 #endif |
|
222 |
|
223 void |
|
224 gst_x_overlay_prepare_xwindow_id (GstXOverlay * overlay) |
|
225 { |
|
226 GstStructure *s; |
|
227 GstMessage *msg; |
|
228 |
|
229 g_return_if_fail (overlay != NULL); |
|
230 g_return_if_fail (GST_IS_X_OVERLAY (overlay)); |
|
231 |
|
232 GST_LOG_OBJECT (GST_OBJECT (overlay), "prepare xwindow_id"); |
|
233 s = gst_structure_new ("prepare-xwindow-id", NULL); |
|
234 msg = gst_message_new_element (GST_OBJECT (overlay), s); |
|
235 gst_element_post_message (GST_ELEMENT (overlay), msg); |
|
236 } |
|
237 |
|
238 /** |
|
239 * gst_x_overlay_expose: |
|
240 * @overlay: a #GstXOverlay to expose. |
|
241 * |
|
242 * Tell an overlay that it has been exposed. This will redraw the current frame |
|
243 * in the drawable even if the pipeline is PAUSED. |
|
244 */ |
|
245 #ifdef __SYMBIAN32__ |
|
246 EXPORT_C |
|
247 #endif |
|
248 |
|
249 void |
|
250 gst_x_overlay_expose (GstXOverlay * overlay) |
|
251 { |
|
252 GstXOverlayClass *klass; |
|
253 |
|
254 g_return_if_fail (overlay != NULL); |
|
255 g_return_if_fail (GST_IS_X_OVERLAY (overlay)); |
|
256 |
|
257 klass = GST_X_OVERLAY_GET_CLASS (overlay); |
|
258 |
|
259 if (klass->expose) { |
|
260 klass->expose (overlay); |
|
261 } |
|
262 } |
|
263 |
|
264 /** |
|
265 * gst_x_overlay_handle_events: |
|
266 * @overlay: a #GstXOverlay to expose. |
|
267 * @handle_events: a #gboolean indicating if events should be handled or not. |
|
268 * |
|
269 * Tell an overlay that it should handle events from the window system. These |
|
270 * events are forwared upstream as navigation events. In some window system, |
|
271 * events are not propagated in the window hierarchy if a client is listening |
|
272 * for them. This method allows you to disable events handling completely |
|
273 * from the XOverlay. |
|
274 */ |
|
275 #ifdef __SYMBIAN32__ |
|
276 EXPORT_C |
|
277 #endif |
|
278 |
|
279 void |
|
280 gst_x_overlay_handle_events (GstXOverlay * overlay, gboolean handle_events) |
|
281 { |
|
282 GstXOverlayClass *klass; |
|
283 |
|
284 g_return_if_fail (overlay != NULL); |
|
285 g_return_if_fail (GST_IS_X_OVERLAY (overlay)); |
|
286 |
|
287 klass = GST_X_OVERLAY_GET_CLASS (overlay); |
|
288 |
|
289 if (klass->handle_events) { |
|
290 klass->handle_events (overlay, handle_events); |
|
291 } |
|
292 } |