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 static gboolean option_fullscreen
= FALSE
;
14 static gint option_screens
= 1;
15 static gboolean option_overlay
= FALSE
;
18 typedef struct windows_s
{
26 bus_call(GstBus
* bus
, GstMessage
*msg
, gpointer data
)
28 windows_t
*w
= (windows_t
*)data
;
29 if (GST_MESSAGE_TYPE(msg
) == GST_MESSAGE_ELEMENT
&&
30 gst_structure_has_name(msg
->structure
, "prepare-xwindow-id")){
31 g_print("Got prepare-xwindow-id msg\n");
32 for (int i
= 0; i
< 2; i
++){
33 gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(w
->sinks
[i
]),
40 toggle_fullscreen(GtkWidget
*widget
){
41 GdkWindowState state
= gdk_window_get_state(GDK_WINDOW(widget
->window
));
42 if (state
== GDK_WINDOW_STATE_FULLSCREEN
){
43 gtk_window_unfullscreen(GTK_WINDOW(widget
));
46 gtk_window_fullscreen(GTK_WINDOW(widget
));
52 key_press_event_cb(GtkWidget
*widget
, GdkEventKey
*event
, gpointer data
)
54 g_print("got key %c\n", event
->keyval
);
55 switch (event
->keyval
){
57 toggle_fullscreen(widget
);
60 g_signal_emit_by_name(widget
, "destroy");
68 void destroy_cb(GtkWidget
* widget
, gpointer data
)
70 GMainLoop
*loop
= (GMainLoop
*) data
;
71 g_print("Window destroyed\n");
72 g_main_loop_quit(loop
);
76 video_widget_realize_cb (GtkWidget
* widget
, gpointer data
)
78 windows_t
*w
= (windows_t
*)data
;
80 w
->windows
[w
->n
] = GDK_WINDOW_XID(GDK_WINDOW(widget
->window
));
83 g_print("wtf, there seem to be %d windows!\n", w
->n
);
91 set_up_window(GMainLoop
*loop
, GtkWidget
*window
){
92 static const GdkColor black
= {0, 0, 0, 0};
93 gtk_window_set_default_size(GTK_WINDOW(window
), WIDTH
, HEIGHT
);
95 if (option_fullscreen
){
96 gtk_window_fullscreen(GTK_WINDOW(window
));
99 //GdkScreen *screen = gdk_display_get_screen(0|1);
100 //gtk_window_set_screen(GTK_WINDOW(window), screen);
102 // attach key press signal to key press callback
103 gtk_widget_set_events(window
, GDK_KEY_PRESS_MASK
);
104 g_signal_connect(G_OBJECT(window
), "key-press-event", G_CALLBACK(key_press_event_cb
), NULL
);
105 g_signal_connect(G_OBJECT(window
), "destroy", G_CALLBACK(destroy_cb
), loop
);
107 gtk_widget_modify_bg(window
, GTK_STATE_NORMAL
, &black
);
108 gtk_widget_show_all(window
);
112 static GOptionEntry entries
[] =
114 { "full-screen", 'f', 0, G_OPTION_ARG_NONE
, &option_fullscreen
, "run full screen", NULL
},
115 { "screens", 's', 0, G_OPTION_ARG_INT
, &option_screens
, "Use this many screens", "S" },
116 { "overlay", 'o', 0, G_OPTION_ARG_NONE
, &option_overlay
, "Use some kind of overlay", NULL
},
121 gint
main (gint argc
, gchar
*argv
[])
124 gst_init (&argc
, &argv
);
125 //gtk_init (&argc, &argv);
127 GError
*error
= NULL
;
128 gtk_init_with_args (&argc
, &argv
,
134 /* herein we count windows and map them to sinks */
138 GMainLoop
*loop
= g_main_loop_new(NULL
, FALSE
);
139 GtkWidget
*window1
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
140 GtkWidget
*window2
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
141 g_signal_connect (window1
, "realize",
142 G_CALLBACK (video_widget_realize_cb
), &windows
);
143 g_signal_connect (window2
, "realize",
144 G_CALLBACK (video_widget_realize_cb
), &windows
);
146 GstElement
*sink1
= gst_element_factory_make("ximagesink", "sink1");
147 GstElement
*sink2
= gst_element_factory_make("ximagesink", "sink2");
148 GstElement
*pipeline
= (GstElement
*)make_dual_pipeline(sink1
, sink2
);
150 windows
.sinks
[0] = sink1
;
151 windows
.sinks
[1] = sink2
;
153 set_up_window(loop
, window1
);
154 set_up_window(loop
, window2
);
156 GstBus
*bus
= gst_pipeline_get_bus(GST_PIPELINE(pipeline
));
157 gst_bus_add_watch(bus
, (GstBusFunc
)bus_call
, &windows
);
158 gst_object_unref (bus
);
160 gst_element_set_state(pipeline
, GST_STATE_PLAYING
);
162 g_main_loop_run(loop
);
164 gst_element_set_state (pipeline
, GST_STATE_NULL
);
165 gst_object_unref (pipeline
);