3 * Copyright (C) 2008-2009 Filippo Argiolas <filippo.argiolas@gmail.com>
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.
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.
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.
24 #define GLIB_DISABLE_DEPRECATION_WARNINGS
29 #include <gdk-pixbuf/gdk-pixbuf.h>
31 #include "../gstgtk.h"
33 #include <gst/video/videooverlay.h>
36 static GstBusSyncReply
37 create_window (GstBus * bus, GstMessage * message, GtkWidget * widget)
39 /* ignore anything but 'prepare-window-handle' element messages */
40 if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT)
43 if (!gst_is_video_overlay_prepare_window_handle_message (message))
46 g_print ("setting window handle\n");
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
54 gst_message_unref (message);
61 end_stream_cb (GstBus * bus, GstMessage * message, GstElement * pipeline)
63 switch (GST_MESSAGE_TYPE (message)) {
65 g_print ("End of stream\n");
67 gst_element_set_state (pipeline, GST_STATE_NULL);
68 gst_object_unref (pipeline);
71 case GST_MESSAGE_ERROR:
76 gst_message_parse_error (message, &err, &debug);
78 g_print ("Error: %s\n", err->message);
82 g_print ("Debug details: %s\n", debug);
86 gst_element_set_state (pipeline, GST_STATE_NULL);
87 gst_object_unref (pipeline);
97 expose_cb (GtkWidget * widget, gpointer unused, gpointer data)
99 GstVideoOverlay *overlay =
100 GST_VIDEO_OVERLAY (gst_bin_get_by_interface (GST_BIN (data),
101 GST_TYPE_VIDEO_OVERLAY));
103 gst_video_overlay_expose (overlay);
104 gst_object_unref (overlay);
110 destroy_cb (GtkWidget * widget, GdkEvent * event, GstElement * pipeline)
112 g_message ("destroy callback");
114 gst_element_set_state (pipeline, GST_STATE_NULL);
115 gst_object_unref (pipeline);
121 apply_fx (GtkWidget * widget, gpointer data)
128 G_PARAM_SPEC_ENUM (g_object_class_find_property (G_OBJECT_GET_CLASS
129 (G_OBJECT (data)), "effect")
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,
135 g_object_set (G_OBJECT (data), "effect", g_enum_get_value_by_nick (p_class,
141 play_cb (GtkWidget * widget, gpointer data)
143 g_message ("playing");
144 gst_element_set_state (GST_ELEMENT (data), GST_STATE_PLAYING);
149 null_cb (GtkWidget * widget, gpointer data)
151 g_message ("nulling");
152 gst_element_set_state (GST_ELEMENT (data), GST_STATE_NULL);
157 ready_cb (GtkWidget * widget, gpointer data)
159 g_message ("readying");
160 gst_element_set_state (GST_ELEMENT (data), GST_STATE_READY);
165 pause_cb (GtkWidget * widget, gpointer data)
167 g_message ("pausing");
168 gst_element_set_state (GST_ELEMENT (data), GST_STATE_PAUSED);
173 main (gint argc, gchar * argv[])
175 GstStateChangeReturn ret;
176 GstElement *pipeline;
177 GstElement *upload, *filter, *sink;
178 GstElement *sourcebin;
180 GError *error = NULL;
184 GtkWidget *vbox, *combo;
186 GtkWidget *play, *pause, *null, *ready;
188 gchar **source_desc_array = NULL;
189 gchar *source_desc = NULL;
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}
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);
209 g_option_context_free (context);
211 if (source_desc_array != NULL) {
212 source_desc = g_strjoinv (" ", source_desc_array);
213 g_strfreev (source_desc_array);
215 if (source_desc == NULL) {
218 ("videotestsrc ! video/x-raw, width=352, height=288 ! identity");
222 gst_parse_bin_from_description (g_strdup (source_desc), TRUE, &error);
223 g_free (source_desc);
225 g_print ("Error while parsing source bin description: %s\n",
226 GST_STR_NULL (error->message));
230 g_set_application_name ("gst-gl-effects test app");
232 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
233 gtk_container_set_border_width (GTK_CONTAINER (window), 3);
235 pipeline = gst_pipeline_new ("pipeline");
237 upload = gst_element_factory_make ("glupload", NULL);
238 filter = gst_element_factory_make ("gleffects", "flt");
239 sink = gst_element_factory_make ("glimagesink", "glsink");
241 gst_bin_add_many (GST_BIN (pipeline), sourcebin, upload, filter, sink, NULL);
243 if (!gst_element_link_many (sourcebin, upload, filter, sink, NULL)) {
244 g_print ("Failed to link one or more elements!\n");
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);
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),
258 g_signal_connect (bus, "message::warning", G_CALLBACK (end_stream_cb),
260 g_signal_connect (bus, "message::eos", G_CALLBACK (end_stream_cb), pipeline);
262 gst_bus_set_sync_handler (bus, (GstBusSyncHandler) create_window, screen,
264 gst_object_unref (bus);
266 gtk_widget_set_size_request (screen, 640, 480); // 500 x 376
268 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
270 gtk_box_pack_start (GTK_BOX (vbox), screen, TRUE, TRUE, 0);
272 combo = gtk_combo_box_text_new ();
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");
291 g_signal_connect (G_OBJECT (combo), "changed", G_CALLBACK (apply_fx), filter);
293 gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, FALSE, 0);
295 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
297 play = gtk_button_new_with_label ("PLAY");
299 g_signal_connect (G_OBJECT (play), "clicked", G_CALLBACK (play_cb), pipeline);
301 pause = gtk_button_new_with_label ("PAUSE");
303 g_signal_connect (G_OBJECT (pause), "clicked",
304 G_CALLBACK (pause_cb), pipeline);
306 null = gtk_button_new_with_label ("NULL");
308 g_signal_connect (G_OBJECT (null), "clicked", G_CALLBACK (null_cb), pipeline);
310 ready = gtk_button_new_with_label ("READY");
312 g_signal_connect (G_OBJECT (ready), "clicked",
313 G_CALLBACK (ready_cb), pipeline);
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);
320 gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
322 gtk_container_add (GTK_CONTAINER (window), vbox);
324 g_signal_connect (screen, "draw", G_CALLBACK (expose_cb), pipeline);
325 g_signal_connect (screen, "configure-event", G_CALLBACK (expose_cb),
327 gtk_widget_realize (screen);
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");
335 gtk_widget_show_all (GTK_WIDGET (window));