Added gst-plugins-base-subtitles0.10-0.10.34 for Meego Harmattan 1.2
[mafwsubrenderer] / gst-plugins-base-subtitles0.10 / tests / icles / test-xoverlay.c
1 /* GStreamer
2  * Copyright (C) <2008> Stefan Kost <ensonic@users.sf.net>
3  *
4  * test-xoverlay: test xoverlay custom event handling and subregions
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 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <stdlib.h>
27 #include <string.h>
28 #include <math.h>
29
30 #include <glib.h>
31 #include <gdk/gdkx.h>
32 #include <gtk/gtk.h>
33
34 #include <gst/gst.h>
35 #include <gst/interfaces/xoverlay.h>
36 #include <gst/video/gstvideosink.h>
37
38 #if !GTK_CHECK_VERSION (2, 17, 7)
39 static void
40 gtk_widget_get_allocation (GtkWidget * w, GtkAllocation * a)
41 {
42   *a = w->allocation;
43 }
44 #endif
45
46 static struct
47 {
48   gint w, h;
49   GstXOverlay *overlay;
50   GtkWidget *widget;
51   gdouble a, p;
52   GstVideoRectangle rect;
53   gboolean running;
54 } anim_state;
55
56 static gboolean verbose = FALSE;
57
58 static gboolean
59 animate_render_rect (gpointer user_data)
60 {
61   if (anim_state.running) {
62     GstVideoRectangle *r = &anim_state.rect;
63     gdouble s = sin (3.0 * anim_state.a);
64     gdouble c = cos (2.0 * anim_state.a);
65
66     anim_state.a += anim_state.p;
67     if (anim_state.a > (M_PI + M_PI))
68       anim_state.a -= (M_PI + M_PI);
69
70     r->w = anim_state.w / 2;
71     r->x = (r->w - (r->w / 2)) + c * (r->w / 2);
72     r->h = anim_state.h / 2;
73     r->y = (r->h - (r->h / 2)) + s * (r->h / 2);
74
75     gst_x_overlay_set_render_rectangle (anim_state.overlay, r->x, r->y,
76         r->w, r->h);
77     gtk_widget_queue_draw (anim_state.widget);
78   }
79   return TRUE;
80 }
81
82 static gboolean
83 handle_resize_cb (GtkWidget * widget, GdkEventConfigure * event,
84     gpointer user_data)
85 {
86   GtkAllocation allocation;
87
88   gtk_widget_get_allocation (widget, &allocation);
89
90   if (verbose) {
91     g_print ("resize(%p): %dx%d\n", widget, allocation.width,
92         allocation.height);
93   }
94   anim_state.w = allocation.width;
95   anim_state.h = allocation.height;
96   animate_render_rect (NULL);
97
98   return FALSE;
99 }
100
101 static gboolean
102 handle_expose_cb (GtkWidget * widget, GdkEventExpose * event,
103     gpointer user_data)
104 {
105   GstVideoRectangle *r = &anim_state.rect;
106   GtkAllocation allocation;
107   GdkWindow *window;
108   GtkStyle *style;
109   cairo_t *cr;
110
111   style = gtk_widget_get_style (widget);
112   window = gtk_widget_get_window (widget);
113   gtk_widget_get_allocation (widget, &allocation);
114   cr = gdk_cairo_create (window);
115
116   gdk_cairo_set_source_color (cr, &style->bg[GTK_STATE_NORMAL]);
117
118   /* we should only redraw outside of the video rect! */
119   cairo_rectangle (cr, 0, event->area.y, r->x, event->area.height);
120   cairo_rectangle (cr, r->x + r->w, event->area.y,
121       allocation.width - (r->x + r->w), event->area.height);
122
123   cairo_rectangle (cr, event->area.x, 0, event->area.width, r->y);
124   cairo_rectangle (cr, event->area.x, r->y + r->h,
125       event->area.width, allocation.height - (r->y + r->h));
126
127   cairo_fill (cr);
128
129   cairo_destroy (cr);
130
131   if (verbose) {
132     g_print ("expose(%p)\n", widget);
133   }
134   gst_x_overlay_expose (anim_state.overlay);
135   return FALSE;
136 }
137
138 static void
139 window_closed (GtkWidget * widget, GdkEvent * event, gpointer user_data)
140 {
141   GstElement *pipeline = user_data;
142
143   if (verbose) {
144     g_print ("stopping\n");
145   }
146   anim_state.running = FALSE;
147   gtk_widget_hide (widget);
148   gst_element_set_state (pipeline, GST_STATE_NULL);
149   gtk_main_quit ();
150 }
151
152 gint
153 main (gint argc, gchar ** argv)
154 {
155   GdkWindow *video_window_xwindow;
156   GtkWidget *window, *video_window;
157   GstElement *pipeline, *src, *sink;
158   GstStateChangeReturn sret;
159   gulong embed_xid = 0;
160   gboolean force_aspect = FALSE, draw_borders = FALSE;
161
162   if (!g_thread_supported ())
163     g_thread_init (NULL);
164
165   gst_init (&argc, &argv);
166   gtk_init (&argc, &argv);
167
168   if (argc) {
169     gint arg;
170     for (arg = 0; arg < argc; arg++) {
171       if (!strcmp (argv[arg], "-a"))
172         force_aspect = TRUE;
173       else if (!strcmp (argv[arg], "-b"))
174         draw_borders = TRUE;
175       else if (!strcmp (argv[arg], "-v"))
176         verbose = TRUE;
177     }
178   }
179
180   /* prepare the pipeline */
181
182   pipeline = gst_pipeline_new ("xvoverlay");
183   src = gst_element_factory_make ("videotestsrc", NULL);
184   sink = gst_element_factory_make ("xvimagesink", NULL);
185   gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL);
186   gst_element_link (src, sink);
187
188   g_object_set (G_OBJECT (sink), "handle-events", FALSE,
189       "force-aspect-ratio", force_aspect, "draw-borders", draw_borders, NULL);
190
191   /* prepare the ui */
192
193   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
194   g_signal_connect (G_OBJECT (window), "delete-event",
195       G_CALLBACK (window_closed), (gpointer) pipeline);
196   gtk_window_set_default_size (GTK_WINDOW (window), 320, 240);
197
198   video_window = gtk_drawing_area_new ();
199   gtk_widget_set_double_buffered (video_window, FALSE);
200   gtk_container_add (GTK_CONTAINER (window), video_window);
201
202   /* show the gui and play */
203   gtk_widget_show_all (window);
204
205   /* realize window now so that the video window gets created and we can
206    * obtain its XID before the pipeline is started up and the videosink
207    * asks for the XID of the window to render onto */
208   gtk_widget_realize (window);
209
210   video_window_xwindow = gtk_widget_get_window (video_window);
211   embed_xid = GDK_WINDOW_XID (video_window_xwindow);
212   if (verbose) {
213     g_print ("Window realize: got XID %lu\n", embed_xid);
214   }
215
216   /* we know what the video sink is in this case (xvimagesink), so we can
217    * just set it directly here now (instead of waiting for a prepare-xwindow-id
218    * element message in a sync bus handler and setting it there) */
219   gst_x_overlay_set_window_handle (GST_X_OVERLAY (sink), embed_xid);
220
221   anim_state.overlay = GST_X_OVERLAY (sink);
222   anim_state.widget = video_window;
223   anim_state.w = 320;
224   anim_state.h = 240;
225   anim_state.a = 0.0;
226   anim_state.p = (M_PI + M_PI) / 200.0;
227
228   handle_resize_cb (video_window, NULL, sink);
229   g_signal_connect (video_window, "configure-event",
230       G_CALLBACK (handle_resize_cb), NULL);
231   g_signal_connect (video_window, "expose-event",
232       G_CALLBACK (handle_expose_cb), NULL);
233
234   g_timeout_add (50, (GSourceFunc) animate_render_rect, NULL);
235
236   /* run the pipeline */
237   sret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
238   if (sret == GST_STATE_CHANGE_FAILURE)
239     gst_element_set_state (pipeline, GST_STATE_NULL);
240   else {
241     anim_state.running = TRUE;
242     gtk_main ();
243   }
244
245   gst_object_unref (pipeline);
246   return 0;
247 }