gl/examples/fxtest: add needed glupload to the pipeline
[platform/upstream/gstreamer.git] / tests / examples / gl / gtk / fxtest / fxtest.c
1 /*
2  * GStreamer
3  * Copyright (C) 2008-2009 Filippo Argiolas <filippo.argiolas@gmail.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library 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 GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #define GLIB_DISABLE_DEPRECATION_WARNINGS
25
26 #include <gst/gst.h>
27 #include <gtk/gtk.h>
28 #include <gdk/gdk.h>
29 #include <gdk-pixbuf/gdk-pixbuf.h>
30
31 #include "../gstgtk.h"
32
33 #include <gst/video/videooverlay.h>
34
35
36 static GstBusSyncReply
37 create_window (GstBus * bus, GstMessage * message, GtkWidget * widget)
38 {
39   /* ignore anything but 'prepare-window-handle' element messages */
40   if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT)
41     return GST_BUS_PASS;
42
43   if (!gst_is_video_overlay_prepare_window_handle_message (message))
44     return GST_BUS_PASS;
45
46   g_print ("setting window handle\n");
47
48   /* do not call gdk_window_ensure_native for the first time here because
49    * we are in a different thread than the main thread
50    * (and the main thread the one) */
51   gst_video_overlay_set_gtk_window (GST_VIDEO_OVERLAY (GST_MESSAGE_SRC
52           (message)), widget);
53
54   gst_message_unref (message);
55
56   return GST_BUS_DROP;
57 }
58
59
60 static void
61 end_stream_cb (GstBus * bus, GstMessage * message, GstElement * pipeline)
62 {
63   switch (GST_MESSAGE_TYPE (message)) {
64     case GST_MESSAGE_EOS:
65       g_print ("End of stream\n");
66
67       gst_element_set_state (pipeline, GST_STATE_NULL);
68       gst_object_unref (pipeline);
69       gtk_main_quit ();
70       break;
71     case GST_MESSAGE_ERROR:
72     {
73       gchar *debug = NULL;
74       GError *err = NULL;
75
76       gst_message_parse_error (message, &err, &debug);
77
78       g_print ("Error: %s\n", err->message);
79       g_clear_error (&err);
80
81       if (debug) {
82         g_print ("Debug details: %s\n", debug);
83         g_free (debug);
84       }
85
86       gst_element_set_state (pipeline, GST_STATE_NULL);
87       gst_object_unref (pipeline);
88       gtk_main_quit ();
89       break;
90     }
91     default:
92       break;
93   }
94 }
95
96 static gboolean
97 expose_cb (GtkWidget * widget, gpointer unused, gpointer data)
98 {
99   GstVideoOverlay *overlay =
100       GST_VIDEO_OVERLAY (gst_bin_get_by_interface (GST_BIN (data),
101           GST_TYPE_VIDEO_OVERLAY));
102
103   gst_video_overlay_expose (overlay);
104   gst_object_unref (overlay);
105
106   return FALSE;
107 }
108
109 static void
110 destroy_cb (GtkWidget * widget, GdkEvent * event, GstElement * pipeline)
111 {
112   g_message ("destroy callback");
113
114   gst_element_set_state (pipeline, GST_STATE_NULL);
115   gst_object_unref (pipeline);
116
117   gtk_main_quit ();
118 }
119
120 static gboolean
121 apply_fx (GtkWidget * widget, gpointer data)
122 {
123   gchar *fx;
124   GEnumClass *p_class;
125
126 /* heeeellppppp!! */
127   p_class =
128       G_PARAM_SPEC_ENUM (g_object_class_find_property (G_OBJECT_GET_CLASS
129           (G_OBJECT (data)), "effect")
130       )->enum_class;
131
132   fx = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (widget));
133   g_print ("setting: %s - %s\n", fx, g_enum_get_value_by_nick (p_class,
134           fx)->value_name);
135   g_object_set (G_OBJECT (data), "effect", g_enum_get_value_by_nick (p_class,
136           fx)->value, NULL);
137   return FALSE;
138 }
139
140 static gboolean
141 play_cb (GtkWidget * widget, gpointer data)
142 {
143   g_message ("playing");
144   gst_element_set_state (GST_ELEMENT (data), GST_STATE_PLAYING);
145   return FALSE;
146 }
147
148 static gboolean
149 null_cb (GtkWidget * widget, gpointer data)
150 {
151   g_message ("nulling");
152   gst_element_set_state (GST_ELEMENT (data), GST_STATE_NULL);
153   return FALSE;
154 }
155
156 static gboolean
157 ready_cb (GtkWidget * widget, gpointer data)
158 {
159   g_message ("readying");
160   gst_element_set_state (GST_ELEMENT (data), GST_STATE_READY);
161   return FALSE;
162 }
163
164 static gboolean
165 pause_cb (GtkWidget * widget, gpointer data)
166 {
167   g_message ("pausing");
168   gst_element_set_state (GST_ELEMENT (data), GST_STATE_PAUSED);
169   return FALSE;
170 }
171
172 gint
173 main (gint argc, gchar * argv[])
174 {
175   GstStateChangeReturn ret;
176   GstElement *pipeline;
177   GstElement *upload, *filter, *sink;
178   GstElement *sourcebin;
179   GstBus *bus;
180   GError *error = NULL;
181
182   GtkWidget *window;
183   GtkWidget *screen;
184   GtkWidget *vbox, *combo;
185   GtkWidget *hbox;
186   GtkWidget *play, *pause, *null, *ready;
187
188   gchar **source_desc_array = NULL;
189   gchar *source_desc = NULL;
190
191   GOptionContext *context;
192   GOptionEntry options[] = {
193     {"source-bin", 's', 0, G_OPTION_ARG_STRING_ARRAY, &source_desc_array,
194         "Use a custom source bin description (gst-launch style)", NULL}
195     ,
196     {NULL}
197   };
198
199   context = g_option_context_new (NULL);
200   g_option_context_add_main_entries (context, options, NULL);
201   g_option_context_add_group (context, gst_init_get_option_group ());
202   g_option_context_add_group (context, gtk_get_option_group (TRUE));
203   if (!g_option_context_parse (context, &argc, &argv, &error)) {
204     g_print ("Inizialization error: %s\n", GST_STR_NULL (error->message));
205     g_option_context_free (context);
206     g_clear_error (&error);
207     return -1;
208   }
209   g_option_context_free (context);
210
211   if (source_desc_array != NULL) {
212     source_desc = g_strjoinv (" ", source_desc_array);
213     g_strfreev (source_desc_array);
214   }
215   if (source_desc == NULL) {
216     source_desc =
217         g_strdup
218         ("videotestsrc ! video/x-raw, width=352, height=288 ! identity");
219   }
220
221   sourcebin =
222       gst_parse_bin_from_description (g_strdup (source_desc), TRUE, &error);
223   g_free (source_desc);
224   if (error) {
225     g_print ("Error while parsing source bin description: %s\n",
226         GST_STR_NULL (error->message));
227     return -1;
228   }
229
230   g_set_application_name ("gst-gl-effects test app");
231
232   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
233   gtk_container_set_border_width (GTK_CONTAINER (window), 3);
234
235   pipeline = gst_pipeline_new ("pipeline");
236
237   upload = gst_element_factory_make ("glupload", NULL);
238   filter = gst_element_factory_make ("gleffects", "flt");
239   sink = gst_element_factory_make ("glimagesink", "glsink");
240
241   gst_bin_add_many (GST_BIN (pipeline), sourcebin, upload, filter, sink, NULL);
242
243   if (!gst_element_link_many (sourcebin, upload, filter, sink, NULL)) {
244     g_print ("Failed to link one or more elements!\n");
245     return -1;
246   }
247
248   g_signal_connect (G_OBJECT (window), "delete-event",
249       G_CALLBACK (destroy_cb), pipeline);
250   g_signal_connect (G_OBJECT (window), "destroy-event",
251       G_CALLBACK (destroy_cb), pipeline);
252
253   screen = gtk_drawing_area_new ();
254   bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
255   gst_bus_add_signal_watch (bus);
256   g_signal_connect (bus, "message::error", G_CALLBACK (end_stream_cb),
257       pipeline);
258   g_signal_connect (bus, "message::warning", G_CALLBACK (end_stream_cb),
259       pipeline);
260   g_signal_connect (bus, "message::eos", G_CALLBACK (end_stream_cb), pipeline);
261
262   gst_bus_set_sync_handler (bus, (GstBusSyncHandler) create_window, screen,
263       NULL);
264   gst_object_unref (bus);
265
266   gtk_widget_set_size_request (screen, 640, 480);       // 500 x 376
267
268   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
269
270   gtk_box_pack_start (GTK_BOX (vbox), screen, TRUE, TRUE, 0);
271
272   combo = gtk_combo_box_text_new ();
273
274   gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "identity");
275   gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "mirror");
276   gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "squeeze");
277   gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "stretch");
278   gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "fisheye");
279   gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "twirl");
280   gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "bulge");
281   gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "tunnel");
282   gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "square");
283   gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "heat");
284   gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "xpro");
285   gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "lumaxpro");
286   gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "sepia");
287   gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "xray");
288   gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "sin");
289   gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "glow");
290
291   g_signal_connect (G_OBJECT (combo), "changed", G_CALLBACK (apply_fx), filter);
292
293   gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, FALSE, 0);
294
295   hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
296
297   play = gtk_button_new_with_label ("PLAY");
298
299   g_signal_connect (G_OBJECT (play), "clicked", G_CALLBACK (play_cb), pipeline);
300
301   pause = gtk_button_new_with_label ("PAUSE");
302
303   g_signal_connect (G_OBJECT (pause), "clicked",
304       G_CALLBACK (pause_cb), pipeline);
305
306   null = gtk_button_new_with_label ("NULL");
307
308   g_signal_connect (G_OBJECT (null), "clicked", G_CALLBACK (null_cb), pipeline);
309
310   ready = gtk_button_new_with_label ("READY");
311
312   g_signal_connect (G_OBJECT (ready), "clicked",
313       G_CALLBACK (ready_cb), pipeline);
314
315   gtk_box_pack_start (GTK_BOX (hbox), null, TRUE, TRUE, 0);
316   gtk_box_pack_start (GTK_BOX (hbox), ready, TRUE, TRUE, 0);
317   gtk_box_pack_start (GTK_BOX (hbox), play, TRUE, TRUE, 0);
318   gtk_box_pack_start (GTK_BOX (hbox), pause, TRUE, TRUE, 0);
319
320   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
321
322   gtk_container_add (GTK_CONTAINER (window), vbox);
323
324   g_signal_connect (screen, "draw", G_CALLBACK (expose_cb), pipeline);
325   g_signal_connect (screen, "configure-event", G_CALLBACK (expose_cb),
326       pipeline);
327   gtk_widget_realize (screen);
328
329   ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
330   if (ret == GST_STATE_CHANGE_FAILURE) {
331     g_print ("Failed to start up pipeline!\n");
332     return -1;
333   }
334
335   gtk_widget_show_all (GTK_WIDGET (window));
336
337   gtk_main ();
338
339   return 0;
340 }