1 /*
2  * This file is part of gtkD.
3  *
4  * gtkD is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License
6  * as published by the Free Software Foundation; either version 3
7  * of the License, or (at your option) any later version, with
8  * some exceptions, please read the COPYING file.
9  *
10  * gtkD is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with gtkD; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
18  */
19 
20 // generated automatically - do not change
21 // find conversion definition on APILookup.txt
22 // implement new conversion functionalities on the wrap.utils pakage
23 
24 
25 module gstinterfaces.VideoOverlay;
26 
27 private import gstreamer.Element;
28 private import gstreamerc.gstinterfaces;
29 public  import gstreamerc.gstinterfacestypes;
30 
31 
32 /**
33  * <refsect2>
34  * <para>
35  * The #GstVideoOverlay interface is used for 2 main purposes :
36  * <itemizedlist>
37  * <listitem>
38  * <para>
39  * To get a grab on the Window where the video sink element is going to render.
40  * This is achieved by either being informed about the Window identifier that
41  * the video sink element generated, or by forcing the video sink element to use
42  * a specific Window identifier for rendering.
43  * </para>
44  * </listitem>
45  * <listitem>
46  * <para>
47  * To force a redrawing of the latest video frame the video sink element
48  * displayed on the Window. Indeed if the #GstPipeline is in #GST_STATE_PAUSED
49  * state, moving the Window around will damage its content. Application
50  * developers will want to handle the Expose events themselves and force the
51  * video sink element to refresh the Window's content.
52  * </para>
53  * </listitem>
54  * </itemizedlist>
55  * </para>
56  * <para>
57  * Using the Window created by the video sink is probably the simplest scenario,
58  * in some cases, though, it might not be flexible enough for application
59  * developers if they need to catch events such as mouse moves and button
60  * clicks.
61  * </para>
62  * <para>
63  * Setting a specific Window identifier on the video sink element is the most
64  * flexible solution but it has some issues. Indeed the application needs to set
65  * its Window identifier at the right time to avoid internal Window creation
66  * from the video sink element. To solve this issue a #GstMessage is posted on
67  * the bus to inform the application that it should set the Window identifier
68  * immediately. Here is an example on how to do that correctly:
69  * |[
70  * static GstBusSyncReply
71  * create_window (GstBus * bus, GstMessage * message, GstPipeline * pipeline)
72  * {
73  * // ignore anything but 'prepare-window-handle' element messages
74  * if (!gst_is_video_overlay_prepare_window_handle_message (message))
75  * return GST_BUS_PASS;
76  * 
77  * win = XCreateSimpleWindow (disp, root, 0, 0, 320, 240, 0, 0, 0);
78  * 
79  * XSetWindowBackgroundPixmap (disp, win, None);
80  * 
81  * XMapRaised (disp, win);
82  * 
83  * XSync (disp, FALSE);
84  * 
85  * gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (GST_MESSAGE_SRC (message)),
86  * win);
87  * 
88  * gst_message_unref (message);
89  * 
90  * return GST_BUS_DROP;
91  * }
92  * ...
93  * int
94  * main (int argc, char **argv)
95  * {
96  * ...
97  * bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
98  * gst_bus_set_sync_handler (bus, (GstBusSyncHandler) create_window, pipeline,
99  * NULL);
100  * ...
101  * }
102  * ]|
103  * </para>
104  * </refsect2>
105  * <refsect2>
106  * <title>Two basic usage scenarios</title>
107  * <para>
108  * There are two basic usage scenarios: in the simplest case, the application
109  * uses #playbin or #plasink or knows exactly what particular element is used
110  * for video output, which is usually the case when the application creates
111  * the videosink to use (e.g. #xvimagesink, #ximagesink, etc.) itself; in this
112  * case, the application can just create the videosink element, create and
113  * realize the window to render the video on and then
114  * call gst_video_overlay_set_window_handle() directly with the XID or native
115  * window handle, before starting up the pipeline.
116  * As #playbin and #playsink implement the video overlay interface and proxy
117  * it transparently to the actual video sink even if it is created later, this
118  * case also applies when using these elements.
119  * </para>
120  * <para>
121  * In the other and more common case, the application does not know in advance
122  * what GStreamer video sink element will be used for video output. This is
123  * usually the case when an element such as #autovideosink is used.
124  * In this case, the video sink element itself is created
125  * asynchronously from a GStreamer streaming thread some time after the
126  * pipeline has been started up. When that happens, however, the video sink
127  * will need to know right then whether to render onto an already existing
128  * application window or whether to create its own window. This is when it
129  * posts a prepare-window-handle message, and that is also why this message needs
130  * to be handled in a sync bus handler which will be called from the streaming
131  * thread directly (because the video sink will need an answer right then).
132  * </para>
133  * <para>
134  * As response to the prepare-window-handle element message in the bus sync
135  * handler, the application may use gst_video_overlay_set_window_handle() to tell
136  * the video sink to render onto an existing window surface. At this point the
137  * application should already have obtained the window handle / XID, so it
138  * just needs to set it. It is generally not advisable to call any GUI toolkit
139  * functions or window system functions from the streaming thread in which the
140  * prepare-window-handle message is handled, because most GUI toolkits and
141  * windowing systems are not thread-safe at all and a lot of care would be
142  * required to co-ordinate the toolkit and window system calls of the
143  * different threads (Gtk+ users please note: prior to Gtk+ 2.18
144  * GDK_WINDOW_XID() was just a simple structure access, so generally fine to do
145  * within the bus sync handler; this macro was changed to a function call in
146  * Gtk+ 2.18 and later, which is likely to cause problems when called from a
147  * sync handler; see below for a better approach without GDK_WINDOW_XID()
148  * used in the callback).
149  * </para>
150  * </refsect2>
151  * <refsect2>
152  * <title>GstVideoOverlay and Gtk+</title>
153  * <para>
154  * |[
155  * #include &lt;gst/video/videooverlay.h&gt;
156  * #include &lt;gtk/gtk.h&gt;
157  * #ifdef GDK_WINDOWING_X11
158  * #include &lt;gdk/gdkx.h&gt;  // for GDK_WINDOW_XID
159  * #endif
160  * #ifdef GDK_WINDOWING_WIN32
161  * #include &lt;gdk/gdkwin32.h&gt;  // for GDK_WINDOW_HWND
162  * #endif
163  * ...
164  * static guintptr video_window_handle = 0;
165  * ...
166  * static GstBusSyncReply
167  * bus_sync_handler (GstBus * bus, GstMessage * message, gpointer user_data)
168  * {
169  * // ignore anything but 'prepare-window-handle' element messages
170  * if (!gst_is_video_overlay_prepare_window_handle_message (message))
171  * return GST_BUS_PASS;
172  * 
173  * if (video_window_handle != 0) {
174  * GstVideoOverlay *overlay;
175  * 
176  * // GST_MESSAGE_SRC (message) will be the video sink element
177  * overlay = GST_VIDEO_OVERLAY (GST_MESSAGE_SRC (message));
178  * gst_video_overlay_set_window_handle (overlay, video_window_handle);
179  * } else {
180  * g_warning ("Should have obtained video_window_handle by now!");
181  * }
182  * 
183  * gst_message_unref (message);
184  * return GST_BUS_DROP;
185  * }
186  * ...
187  * static void
188  * video_widget_realize_cb (GtkWidget * widget, gpointer data)
189  * {
190  * #if GTK_CHECK_VERSION(2,18,0)
191  * // Tell Gtk+/Gdk to create a native window for this widget instead of
192  * // drawing onto the parent widget.
193  * // This is here just for pedagogical purposes, GDK_WINDOW_XID will call
194  * // it as well in newer Gtk versions
195  * if (!gdk_window_ensure_native (widget->window))
196  * g_error ("Couldn't create native window needed for GstVideoOverlay!");
197  * #endif
198  * 
199  * #ifdef GDK_WINDOWING_X11
200  * {
201  * gulong xid = GDK_WINDOW_XID (gtk_widget_get_window (video_window));
202  * video_window_handle = xid;
203  * }
204  * #endif
205  * #ifdef GDK_WINDOWING_WIN32
206  * {
207  * HWND wnd = GDK_WINDOW_HWND (gtk_widget_get_window (video_window));
208  * video_window_handle = (guintptr) wnd;
209  * }
210  * #endif
211  * }
212  * ...
213  * int
214  * main (int argc, char **argv)
215  * {
216  * GtkWidget *video_window;
217  * GtkWidget *app_window;
218  * ...
219  * app_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
220  * ...
221  * video_window = gtk_drawing_area_new ();
222  * g_signal_connect (video_window, "realize",
223  * G_CALLBACK (video_widget_realize_cb), NULL);
224  * gtk_widget_set_double_buffered (video_window, FALSE);
225  * ...
226  * // usually the video_window will not be directly embedded into the
227  * // application window like this, but there will be many other widgets
228  * // and the video window will be embedded in one of them instead
229  * gtk_container_add (GTK_CONTAINER (ap_window), video_window);
230  * ...
231  * // show the GUI
232  * gtk_widget_show_all (app_window);
233  * 
234  * // realize window now so that the video window gets created and we can
235  * // obtain its XID/HWND before the pipeline is started up and the videosink
236  * // asks for the XID/HWND of the window to render onto
237  * gtk_widget_realize (video_window);
238  * 
239  * // we should have the XID/HWND now
240  * g_assert (video_window_handle != 0);
241  * ...
242  * // set up sync handler for setting the xid once the pipeline is started
243  * bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
244  * gst_bus_set_sync_handler (bus, (GstBusSyncHandler) bus_sync_handler, NULL,
245  * NULL);
246  * gst_object_unref (bus);
247  * ...
248  * gst_element_set_state (pipeline, GST_STATE_PLAYING);
249  * ...
250  * }
251  * ]|
252  * </para>
253  * </refsect2>
254  * <refsect2>
255  * <title>GstVideoOverlay and Qt</title>
256  * <para>
257  * |[
258  * #include &lt;glib.h&gt;
259  * #include &lt;gst/gst.h&gt;
260  * #include &lt;gst/video/videooverlay.h&gt;
261  * 
262  * #include &lt;QApplication&gt;
263  * #include &lt;QTimer&gt;
264  * #include &lt;QWidget&gt;
265  * 
266  * int main(int argc, char *argv[])
267  * {
268  * if (!g_thread_supported ())
269  * g_thread_init (NULL);
270  * 
271  * gst_init (&argc, &argv);
272  * QApplication app(argc, argv);
273  * app.connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit ()));
274  * 
275  * // prepare the pipeline
276  * 
277  * GstElement *pipeline = gst_pipeline_new ("xvoverlay");
278  * GstElement *src = gst_element_factory_make ("videotestsrc", NULL);
279  * GstElement *sink = gst_element_factory_make ("xvimagesink", NULL);
280  * gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL);
281  * gst_element_link (src, sink);
282  * 
283  * // prepare the ui
284  * 
285  * QWidget window;
286  * window.resize(320, 240);
287  * window.show();
288  * 
289  * WId xwinid = window.winId();
290  * gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (sink), xwinid);
291  * 
292  * // run the pipeline
293  * 
294  * GstStateChangeReturn sret = gst_element_set_state (pipeline,
295  * GST_STATE_PLAYING);
296  * if (sret == GST_STATE_CHANGE_FAILURE) {
297  * gst_element_set_state (pipeline, GST_STATE_NULL);
298  * gst_object_unref (pipeline);
299  * // Exit application
300  * QTimer::singleShot(0, QApplication::activeWindow(), SLOT(quit()));
301  * }
302  * 
303  * int ret = app.exec();
304  * 
305  * window.hide();
306  * gst_element_set_state (pipeline, GST_STATE_NULL);
307  * gst_object_unref (pipeline);
308  * 
309  * return ret;
310  * }
311  * ]|
312  * </para>
313  * </refsect2>
314  */
315 public class VideoOverlay
316 {
317 	/** the main Gtk struct */
318 	protected GstVideoOverlay* gstVideoOverlay;
319 	protected bool ownedRef;
320 
321 	/** Get the main Gtk struct */
322 	public GstVideoOverlay* getVideoOverlayStruct()
323 	{
324 		return gstVideoOverlay;
325 	}
326 
327 	/** the main Gtk struct as a void* */
328 	protected void* getStruct()
329 	{
330 		return cast(void*)gstVideoOverlay;
331 	}
332 
333 	/**
334 	 * Sets our main struct and passes it to the parent class.
335 	 */
336 	public this (GstVideoOverlay* gstVideoOverlay, bool ownedRef = false)
337 	{
338 		this.gstVideoOverlay = gstVideoOverlay;
339 		this.ownedRef = ownedRef;
340 	}
341 
342 	/**
343 	 * The Element parameter should usually be
344 	 * your videosink that you want to create your
345 	 * XOverlay with.
346 	 */
347 	public this(Element elem)
348 	{
349 		this( cast(GstVideoOverlay*)elem.getElementStruct() );
350 	}
351 
352 	/**
353 	 */
354 
355 	/**
356 	 * Tell an overlay that it has been exposed. This will redraw the current frame
357 	 * in the drawable even if the pipeline is PAUSED.
358 	 */
359 	public void expose()
360 	{
361 		gst_video_overlay_expose(getVideoOverlayStruct());
362 	}
363 
364 	/**
365 	 * This will post a "have-window-handle" element message on the bus.
366 	 *
367 	 * This function should only be used by video overlay plugin developers.
368 	 *
369 	 * Params:
370 	 *     handle = a platform-specific handle referencing the window
371 	 */
372 	public void gotWindowHandle(size_t handle)
373 	{
374 		gst_video_overlay_got_window_handle(getVideoOverlayStruct(), handle);
375 	}
376 
377 	/**
378 	 * Tell an overlay that it should handle events from the window system. These
379 	 * events are forwarded upstream as navigation events. In some window system,
380 	 * events are not propagated in the window hierarchy if a client is listening
381 	 * for them. This method allows you to disable events handling completely
382 	 * from the #GstVideoOverlay.
383 	 *
384 	 * Params:
385 	 *     handleEvents = a #gboolean indicating if events should be handled or not.
386 	 */
387 	public void handleEvents(bool handleEvents)
388 	{
389 		gst_video_overlay_handle_events(getVideoOverlayStruct(), handleEvents);
390 	}
391 
392 	/**
393 	 * This will post a "prepare-window-handle" element message on the bus
394 	 * to give applications an opportunity to call
395 	 * gst_video_overlay_set_window_handle() before a plugin creates its own
396 	 * window.
397 	 *
398 	 * This function should only be used by video overlay plugin developers.
399 	 */
400 	public void prepareWindowHandle()
401 	{
402 		gst_video_overlay_prepare_window_handle(getVideoOverlayStruct());
403 	}
404 
405 	/**
406 	 * Configure a subregion as a video target within the window set by
407 	 * gst_video_overlay_set_window_handle(). If this is not used or not supported
408 	 * the video will fill the area of the window set as the overlay to 100%.
409 	 * By specifying the rectangle, the video can be overlayed to a specific region
410 	 * of that window only. After setting the new rectangle one should call
411 	 * gst_video_overlay_expose() to force a redraw. To unset the region pass -1 for
412 	 * the @width and @height parameters.
413 	 *
414 	 * This method is needed for non fullscreen video overlay in UI toolkits that
415 	 * do not support subwindows.
416 	 *
417 	 * Params:
418 	 *     x = the horizontal offset of the render area inside the window
419 	 *     y = the vertical offset of the render area inside the window
420 	 *     width = the width of the render area inside the window
421 	 *     height = the height of the render area inside the window
422 	 *
423 	 * Return: %FALSE if not supported by the sink.
424 	 */
425 	public bool setRenderRectangle(int x, int y, int width, int height)
426 	{
427 		return gst_video_overlay_set_render_rectangle(getVideoOverlayStruct(), x, y, width, height) != 0;
428 	}
429 
430 	/**
431 	 * This will call the video overlay's set_window_handle method. You
432 	 * should use this method to tell to an overlay to display video output to a
433 	 * specific window (e.g. an XWindow on X11). Passing 0 as the  @handle will
434 	 * tell the overlay to stop using that window and create an internal one.
435 	 *
436 	 * Params:
437 	 *     handle = a handle referencing the window.
438 	 */
439 	public void setWindowHandle(size_t handle)
440 	{
441 		gst_video_overlay_set_window_handle(getVideoOverlayStruct(), handle);
442 	}
443 }