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