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