#include <gtk/gtk.h>
#include <gst/video/video-overlay-composition.h>
#include <gst/gst.h>
#include <gst/interfaces/xoverlay.h>
#include <gdk/gdkx.h> // for GDK_WINDOW_XID
static gulong video_window_xid = 0;
GtkWidget *video_window;
GtkWidget *app_window;
GtkWidget *fixed;
GtkWidget *label;
static GstBusSyncReply bus_sync_handler (GstBus * bus, GstMessage * message, gpointer user_data)
{
// ignore anything but 'prepare-xwindow-id' element messages
if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT)
return GST_BUS_PASS;
if (!gst_structure_has_name (message->structure, "prepare-xwindow-id"))
return GST_BUS_PASS;
if (video_window_xid != 0) {
GstXOverlay *xoverlay;
// GST_MESSAGE_SRC (message) will be the video sink element
xoverlay = GST_X_OVERLAY (GST_MESSAGE_SRC (message));
gst_x_overlay_set_window_handle (xoverlay, video_window_xid);
} else {
g_warning ("Should have obtained video_window_xid by now!");
}
gst_message_unref (message);
return GST_BUS_DROP;
}
gboolean bus_callback(GstBus *bus, GstMessage *msg, gpointer data)
{
GstElement *player = GST_ELEMENT(data);
switch (GST_MESSAGE_TYPE(msg))
{
case GST_MESSAGE_EOS:
/* restart playback if at end */
g_print("EOS received\n");
if (gst_element_seek(player,
1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH,
GST_SEEK_TYPE_SET, 0.0,
GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) {
g_print("seek ok\n");
}
gst_element_set_state (player, GST_STATE_PLAYING);
return TRUE;
break;
case GST_MESSAGE_STATE_CHANGED:{
GstState old_state, new_state;
gst_message_parse_state_changed (msg, &old_state, &new_state, NULL);
g_print ("Element %s changed state from %s to %s.\n",
GST_OBJECT_NAME (msg->src),
gst_element_state_get_name (old_state),
gst_element_state_get_name (new_state));
break;
}
default:
break;
}
return TRUE;
}
static void
video_widget_realize_cb (GtkWidget * widget, gpointer data)
{
video_window_xid = GDK_WINDOW_XID (video_window->window);
}
int
main (int argc, char **argv)
{
gtk_init(&argc, &argv);
gst_init(&argc, &argv);
app_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size (GTK_WINDOW (app_window), 800,600);
video_window = gtk_drawing_area_new ();
g_signal_connect (video_window, "realize",
G_CALLBACK (video_widget_realize_cb), NULL);
fixed = gtk_fixed_new ();
gtk_widget_set_double_buffered (fixed, FALSE);
gtk_container_add (GTK_CONTAINER (app_window), fixed);
gtk_widget_show (fixed);
gtk_fixed_put (GTK_FIXED (fixed), video_window, 20, 20);
gtk_widget_show (video_window);
gtk_widget_set_size_request (video_window, 600, 400);
gtk_widget_show_all (app_window);
gtk_widget_realize (video_window);
/* we should have the XID now */
g_assert (video_window_xid != 0);
/* set up sync handler for setting the xid once the pipeline is started */
GstElement * pipeline = gst_element_factory_make("playbin2", "play");
g_object_set(G_OBJECT(pipeline), "uri", argv[1], NULL);
GstBus * bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
gst_bus_set_sync_handler (bus, (GstBusSyncHandler) bus_sync_handler, NULL);
gst_bus_add_watch (bus, bus_callback, pipeline);
gst_object_unref (bus);
gst_element_set_state (pipeline, GST_STATE_PLAYING);
gtk_main();
}