2 Largely based on an example by Tristan Matthews
3 http://tristanswork.blogspot.com/2008/09/fullscreen-video-in-gstreamer-with-gtk.html
8 #include <gst/interfaces/xoverlay.h>
13 typedef struct windows_s
{
21 bus_call(GstBus
* bus
, GstMessage
*msg
, gpointer data
)
23 windows_t
*w
= (windows_t
*)data
;
24 if (GST_MESSAGE_TYPE(msg
) == GST_MESSAGE_ELEMENT
&&
25 gst_structure_has_name(msg
->structure
, "prepare-xwindow-id")){
26 g_print("Got prepare-xwindow-id msg\n");
27 for (int i
= 0; i
< 2; i
++){
28 gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(w
->sinks
[i
]),
35 toggle_fullscreen(GtkWidget
*widget
){
36 GdkWindowState state
= gdk_window_get_state(GDK_WINDOW(widget
->window
));
37 if (state
== GDK_WINDOW_STATE_FULLSCREEN
){
38 gtk_window_unfullscreen(GTK_WINDOW(widget
));
41 gtk_window_fullscreen(GTK_WINDOW(widget
));
47 key_press_event_cb(GtkWidget
*widget
, GdkEventKey
*event
, gpointer data
)
49 g_print("got key %c\n", event
->keyval
);
50 switch (event
->keyval
){
52 toggle_fullscreen(widget
);
55 g_signal_emit_by_name(widget
, "destroy");
63 void destroy_cb(GtkWidget
* widget
, gpointer data
)
65 GMainLoop
*loop
= (GMainLoop
*) data
;
66 g_print("Window destroyed\n");
67 g_main_loop_quit(loop
);
71 video_widget_realize_cb (GtkWidget
* widget
, gpointer data
)
73 windows_t
*w
= (windows_t
*)data
;
75 w
->windows
[w
->n
] = GDK_WINDOW_XID(GDK_WINDOW(widget
->window
));
78 g_print("wtf, there seem to be %d windows!\n", w
->n
);
86 set_up_window(GMainLoop
*loop
, GtkWidget
*window
){
87 static const GdkColor black
= {0, 0, 0, 0};
88 gtk_window_set_default_size(GTK_WINDOW(window
), WIDTH
, HEIGHT
);
90 //gtk_window_fullscreen(GTK_WINDOW(widget));
91 //GdkScreen *screen = gdk_display_get_screen(0|1);
92 //gtk_window_set_screen(GTK_WINDOW(window), screen);
94 // attach key press signal to key press callback
95 gtk_widget_set_events(window
, GDK_KEY_PRESS_MASK
);
96 g_signal_connect(G_OBJECT(window
), "key-press-event", G_CALLBACK(key_press_event_cb
), NULL
);
97 g_signal_connect(G_OBJECT(window
), "destroy", G_CALLBACK(destroy_cb
), loop
);
99 gtk_widget_modify_bg(window
, GTK_STATE_NORMAL
, &black
);
100 gtk_widget_show_all(window
);
103 gint
main (gint argc
, gchar
*argv
[])
106 gst_init (&argc
, &argv
);
107 gtk_init (&argc
, &argv
);
109 /* herein we count windows and map them to sinks */
113 GMainLoop
*loop
= g_main_loop_new(NULL
, FALSE
);
114 GtkWidget
*window1
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
115 GtkWidget
*window2
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
116 g_signal_connect (window1
, "realize",
117 G_CALLBACK (video_widget_realize_cb
), &windows
);
118 g_signal_connect (window2
, "realize",
119 G_CALLBACK (video_widget_realize_cb
), &windows
);
121 GstElement
*sink1
= gst_element_factory_make("ximagesink", "sink1");
122 GstElement
*sink2
= gst_element_factory_make("ximagesink", "sink2");
123 GstElement
*pipeline
= (GstElement
*)make_dual_pipeline(sink1
, sink2
);
125 windows
.sinks
[0] = sink1
;
126 windows
.sinks
[1] = sink2
;
128 set_up_window(loop
, window1
);
129 set_up_window(loop
, window2
);
131 GstBus
*bus
= gst_pipeline_get_bus(GST_PIPELINE(pipeline
));
132 gst_bus_add_watch(bus
, (GstBusFunc
)bus_call
, &windows
);
133 gst_object_unref (bus
);
135 gst_element_set_state(pipeline
, GST_STATE_PLAYING
);
137 g_main_loop_run(loop
);
139 gst_element_set_state (pipeline
, GST_STATE_NULL
);
140 gst_object_unref (pipeline
);