-#include <gtk/gtk.h>\r
+#include <gtk/gtk.h>
#include <gst/gst.h>
#include <gdk/gdk.h>
#elif defined (GDK_WINDOWING_QUARTZ)
#include <gdk/gdkquartzwindow.h>
#endif
- \r
-#include <gst/interfaces/xoverlay.h>\r
-#include <memory.h>\r
- \r
-/* Structure to contain all our information, so we can pass it around */\r
-typedef struct _CustomData {\r
- GstElement *playbin2; /* Our one and only pipeline */\r
- GtkWidget *main_window;\r
+
+#include <gst/interfaces/xoverlay.h>
+#include <memory.h>
+
+/* Structure to contain all our information, so we can pass it around */
+typedef struct _CustomData {
+ GstElement *playbin2; /* Our one and only pipeline */
+ GtkWidget *main_window;
GtkWidget *video_window;
GtkWidget *slider;
GstState state;
gint64 duration;
- guintptr embed_xid;\r
-} CustomData;\r
- \r
-/* Forward definition of the message processing function */\r
-static gboolean handle_message (GstBus *bus, GstMessage *msg, CustomData *data);\r
-static GstBusSyncReply bus_sync_handler (GstBus *bus, GstMessage *msg, CustomData *data);\r
- \r
+ guintptr embed_xid;
+} CustomData;
+
+/* Forward definition of the message processing function */
+static gboolean handle_message (GstBus *bus, GstMessage *msg, CustomData *data);
+static GstBusSyncReply bus_sync_handler (GstBus *bus, GstMessage *msg, CustomData *data);
+
static void realize_cb (GtkWidget *widget, CustomData *data) {
GdkWindow *window = gtk_widget_get_window (widget);
data->embed_xid = gdk_quartz_window_get_nsview (window);
#elif defined (GDK_WINDOWING_X11)
data->embed_xid = GDK_WINDOW_XID (window);
-#endif\r
-}\r
- \r
-static void play_cb (GtkButton *button, CustomData *data) {\r
- gst_element_set_state (data->playbin2, GST_STATE_PLAYING);\r
-}\r
- \r
-static void pause_cb (GtkButton *button, CustomData *data) {\r
- gst_element_set_state (data->playbin2, GST_STATE_PAUSED);\r
-}\r
- \r
-static void stop_cb (GtkButton *button, CustomData *data) {\r
- gst_element_set_state (data->playbin2, GST_STATE_READY);\r
-}\r
- \r
+#endif
+}
+
+static void play_cb (GtkButton *button, CustomData *data) {
+ gst_element_set_state (data->playbin2, GST_STATE_PLAYING);
+}
+
+static void pause_cb (GtkButton *button, CustomData *data) {
+ gst_element_set_state (data->playbin2, GST_STATE_PAUSED);
+}
+
+static void stop_cb (GtkButton *button, CustomData *data) {
+ gst_element_set_state (data->playbin2, GST_STATE_READY);
+}
+
static void delete_event_cb (GtkWidget *widget, GdkEvent *event, CustomData *data) {
stop_cb (NULL, data);
gtk_main_quit ();
-}\r
- \r
+}
+
static gboolean draw_cb (GtkWidget *widget, GdkEventExpose *event, CustomData *data) {
if (data->state < GST_STATE_PAUSED) {
GtkAllocation allocation;
*/
return FALSE;
}
- \r
+
static void create_ui (CustomData *data) {
GtkWidget *controls, *main_box;
GtkWidget *play_button, *pause_button, *stop_button;
data->video_window = gtk_drawing_area_new ();
gtk_widget_set_double_buffered (data->video_window, FALSE);
g_signal_connect (data->video_window, "realize", G_CALLBACK (realize_cb), data);
- g_signal_connect (data->video_window, "expose_event", G_CALLBACK (draw_cb), data);\r
+ g_signal_connect (data->video_window, "expose_event", G_CALLBACK (draw_cb), data);
play_button = gtk_button_new_from_stock (GTK_STOCK_MEDIA_PLAY);
g_signal_connect (G_OBJECT (play_button), "clicked", G_CALLBACK (play_cb), data);
gtk_widget_show_all (data->main_window);
- gtk_widget_realize (data->main_window);\r
-}\r
- \r
-static gboolean refresh_ui (CustomData *data) {\r
- GstFormat fmt = GST_FORMAT_TIME;\r
- gint64 current = -1;\r
-\r
- /* We do not want to update anything unless we are in the PLAYING state */\r
- if (data->state != GST_STATE_PLAYING) return TRUE;\r
- \r
- /* If we didn't know it yet, query the stream duration */\r
- if (!GST_CLOCK_TIME_IS_VALID (data->duration)) {\r
- if (!gst_element_query_duration (data->playbin2, &fmt, &data->duration)) {\r
- g_printerr ("Could not query current duration.\n");\r
- } else {\r
- gtk_range_set_range (GTK_RANGE (data->slider), 0, data->duration / GST_SECOND);\r
- }\r
- }\r
- \r
- if (gst_element_query_position (data->playbin2, &fmt, ¤t)) {\r
- gtk_range_set_value (GTK_RANGE (data->slider), current / GST_SECOND);\r
- }\r
- return TRUE;\r
-}\r
- \r
-int main(int argc, char *argv[]) {\r
- CustomData data;\r
- GstStateChangeReturn ret;\r
- GstBus *bus;\r
- \r
- /* Initialize GTK */\r
- gtk_init (&argc, &argv);\r
- \r
- /* Initialize GStreamer */\r
- gst_init (&argc, &argv);\r
- \r
- /* Initialize our data structure */\r
- memset (&data, 0, sizeof (data));\r
- data.duration = GST_CLOCK_TIME_NONE;\r
- \r
- /* Create the elements */\r
- data.playbin2 = gst_element_factory_make ("playbin2", "playbin2");\r
- \r
- if (!data.playbin2) {\r
- g_printerr ("Not all elements could be created.\n");\r
- return -1;\r
- }\r
- \r
- /* Set the URI to play */\r
-// g_object_set (data.playbin2, "uri", "http://docs.gstreamer.com/media/sintel_trailer-480p.webm", NULL);\r
- g_object_set (data.playbin2, "uri", "file:///f:/media/big_buck_bunny_480p.H264.mov", NULL);\r
- \r
- create_ui (&data);\r
- \r
- bus = gst_element_get_bus (data.playbin2);\r
- gst_bus_set_sync_handler (bus, (GstBusSyncHandler)bus_sync_handler, &data);\r
- gst_bus_add_watch (bus, (GstBusFunc)handle_message, &data);\r
- gst_object_unref (bus);\r
- \r
- /* Start playing */\r
- ret = gst_element_set_state (data.playbin2, GST_STATE_PLAYING);\r
- if (ret == GST_STATE_CHANGE_FAILURE) {\r
- g_printerr ("Unable to set the pipeline to the playing state.\n");\r
- gst_object_unref (data.playbin2);\r
- return -1;\r
- }\r
- \r
- g_timeout_add (500, (GSourceFunc)refresh_ui, &data);\r
- // add timeout to refresh UI: query position and duration (if unknown), gtk_range_set_value() on the slider\r
- gtk_main ();\r
- \r
- /* Free resources */\r
- gst_element_set_state (data.playbin2, GST_STATE_NULL);\r
- gst_object_unref (data.playbin2);\r
- return 0;\r
-}\r
- \r
-static gboolean handle_message (GstBus *bus, GstMessage *msg, CustomData *data) {\r
- GError *err;\r
- gchar *debug_info;\r
- \r
- switch (GST_MESSAGE_TYPE (msg)) {\r
- case GST_MESSAGE_ERROR:\r
- gst_message_parse_error (msg, &err, &debug_info);\r
- g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message);\r
- g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none");\r
- g_clear_error (&err);\r
- g_free (debug_info);\r
- gtk_main_quit ();\r
- break;\r
- case GST_MESSAGE_EOS:\r
- g_print ("End-Of-Stream reached.\n");\r
- gst_element_set_state (data->playbin2, GST_STATE_READY);\r
- break;\r
- case GST_MESSAGE_STATE_CHANGED: {\r
- GstState old_state, new_state, pending_state;\r
- gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state);\r
- if (GST_MESSAGE_SRC (msg) == GST_OBJECT (data->playbin2)) {\r
- data->state = new_state;\r
- g_print ("State set to %s\n", gst_element_state_get_name (new_state));\r
- }\r
- } break;\r
- }\r
-\r
- return TRUE;\r
-}\r
-static GstBusSyncReply bus_sync_handler (GstBus *bus, GstMessage *msg, CustomData *data) {\r
- /*ignore anything but 'prepare-xwindow-id' element messages */\r
- if (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_ELEMENT)\r
- return GST_BUS_PASS;\r
- if (!gst_structure_has_name (msg->structure, "prepare-xwindow-id"))\r
- return GST_BUS_PASS;\r
- \r
- if (data->embed_xid != 0) {\r
- /* GST_MESSAGE_SRC (message) will be the video sink element */\r
- GstXOverlay *xoverlay = GST_X_OVERLAY (GST_MESSAGE_SRC (msg));\r
- gst_x_overlay_set_window_handle (xoverlay, data->embed_xid);\r
- } else {\r
- g_warning ("Should have obtained an xid by now!");\r
- }\r
- \r
- gst_message_unref (msg);\r
- return GST_BUS_DROP;\r
-}\r
+ gtk_widget_realize (data->main_window);
+}
+
+static gboolean refresh_ui (CustomData *data) {
+ GstFormat fmt = GST_FORMAT_TIME;
+ gint64 current = -1;
+
+ /* We do not want to update anything unless we are in the PLAYING state */
+ if (data->state != GST_STATE_PLAYING) return TRUE;
+
+ /* If we didn't know it yet, query the stream duration */
+ if (!GST_CLOCK_TIME_IS_VALID (data->duration)) {
+ if (!gst_element_query_duration (data->playbin2, &fmt, &data->duration)) {
+ g_printerr ("Could not query current duration.\n");
+ } else {
+ gtk_range_set_range (GTK_RANGE (data->slider), 0, (gdouble)data->duration / GST_SECOND);
+ }
+ }
+
+ if (gst_element_query_position (data->playbin2, &fmt, ¤t)) {
+ gtk_range_set_value (GTK_RANGE (data->slider), (gdouble)current / GST_SECOND);
+ }
+ return TRUE;
+}
+
+int main(int argc, char *argv[]) {
+ CustomData data;
+ GstStateChangeReturn ret;
+ GstBus *bus;
+
+ /* Initialize GTK */
+ gtk_init (&argc, &argv);
+
+ /* Initialize GStreamer */
+ gst_init (&argc, &argv);
+
+ /* Initialize our data structure */
+ memset (&data, 0, sizeof (data));
+ data.duration = GST_CLOCK_TIME_NONE;
+
+ /* Create the elements */
+ data.playbin2 = gst_element_factory_make ("playbin2", "playbin2");
+
+ if (!data.playbin2) {
+ g_printerr ("Not all elements could be created.\n");
+ return -1;
+ }
+
+ /* Set the URI to play */
+ g_object_set (data.playbin2, "uri", "http://docs.gstreamer.com/media/sintel_trailer-480p.webm", NULL);
+
+ create_ui (&data);
+
+ bus = gst_element_get_bus (data.playbin2);
+ gst_bus_set_sync_handler (bus, (GstBusSyncHandler)bus_sync_handler, &data);
+ gst_bus_add_watch (bus, (GstBusFunc)handle_message, &data);
+ gst_object_unref (bus);
+
+ /* Start playing */
+ ret = gst_element_set_state (data.playbin2, GST_STATE_PLAYING);
+ if (ret == GST_STATE_CHANGE_FAILURE) {
+ g_printerr ("Unable to set the pipeline to the playing state.\n");
+ gst_object_unref (data.playbin2);
+ return -1;
+ }
+
+ g_timeout_add (500, (GSourceFunc)refresh_ui, &data);
+ // add timeout to refresh UI: query position and duration (if unknown), gtk_range_set_value() on the slider
+ gtk_main ();
+
+ /* Free resources */
+ gst_element_set_state (data.playbin2, GST_STATE_NULL);
+ gst_object_unref (data.playbin2);
+ return 0;
+}
+
+static gboolean handle_message (GstBus *bus, GstMessage *msg, CustomData *data) {
+ GError *err;
+ gchar *debug_info;
+
+ switch (GST_MESSAGE_TYPE (msg)) {
+ case GST_MESSAGE_ERROR:
+ gst_message_parse_error (msg, &err, &debug_info);
+ g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message);
+ g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none");
+ g_clear_error (&err);
+ g_free (debug_info);
+ gtk_main_quit ();
+ break;
+ case GST_MESSAGE_EOS:
+ g_print ("End-Of-Stream reached.\n");
+ gst_element_set_state (data->playbin2, GST_STATE_READY);
+ break;
+ case GST_MESSAGE_STATE_CHANGED: {
+ GstState old_state, new_state, pending_state;
+ gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state);
+ if (GST_MESSAGE_SRC (msg) == GST_OBJECT (data->playbin2)) {
+ data->state = new_state;
+ g_print ("State set to %s\n", gst_element_state_get_name (new_state));
+ }
+ } break;
+ }
+
+ return TRUE;
+}
+static GstBusSyncReply bus_sync_handler (GstBus *bus, GstMessage *msg, CustomData *data) {
+ /*ignore anything but 'prepare-xwindow-id' element messages */
+ if (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_ELEMENT)
+ return GST_BUS_PASS;
+ if (!gst_structure_has_name (msg->structure, "prepare-xwindow-id"))
+ return GST_BUS_PASS;
+
+ if (data->embed_xid != 0) {
+ /* GST_MESSAGE_SRC (message) will be the video sink element */
+ GstXOverlay *xoverlay = GST_X_OVERLAY (GST_MESSAGE_SRC (msg));
+ gst_x_overlay_set_window_handle (xoverlay, data->embed_xid);
+ } else {
+ g_warning ("Should have obtained an xid by now!");
+ }
+
+ gst_message_unref (msg);
+ return GST_BUS_DROP;
+}