2 initially based on an example by Tristan Matthews
3 http://tristanswork.blogspot.com/2008/09/fullscreen-video-in-gstreamer-with-gtk.html
7 #include <gst/interfaces/xoverlay.h>
12 GstElement
*global_pipeline
= NULL
;
15 make_multi_pipeline(GstElement
**sinks
, int count
)
17 GstPipeline
*pipeline
= GST_PIPELINE(gst_pipeline_new("sparrow_pipeline"));
18 GstElement
*tee
= pre_tee_pipeline(pipeline
);
22 for (i
= 0; i
< count
; i
++){
23 GstElement
*sink
= gst_element_factory_make("ximagesink", NULL
);
26 //(pipeline, tee, sink, int rngseed, int colour, timer flag, int debug flag)
27 /* timer should only run on one of them. colour >= 3 is undefined */
28 int debug
= option_debug
== i
;
29 int timer
= option_timer
== i
;
30 if (option_reload
!= NULL
){
31 if (option_reload
[i
] == NULL
){
32 g_critical("You can't reload some screens and not others!");
35 reload
= option_reload
[i
];
37 if (option_save
&& option_save
[i
]){
38 save
= option_save
[i
];
40 post_tee_pipeline(pipeline
, tee
, sink
, i
, i
+ 1, timer
, debug
, save
, reload
);
43 /*add a branch saving the video to a file */
44 mjpeg_branch(pipeline
, tee
);
52 toggle_fullscreen(GtkWidget
*widget
){
53 GdkWindowState state
= gdk_window_get_state(GDK_WINDOW(widget
->window
));
54 if (state
== GDK_WINDOW_STATE_FULLSCREEN
){
55 gtk_window_unfullscreen(GTK_WINDOW(widget
));
58 gtk_window_fullscreen(GTK_WINDOW(widget
));
63 key_press_event_cb(GtkWidget
*widget
, GdkEventKey
*event
, gpointer data
)
65 switch (event
->keyval
){
67 toggle_fullscreen(widget
);
70 g_signal_emit_by_name(widget
, "destroy");
79 window_closed(GtkWidget
*widget
, GdkEvent
*event
, gpointer user_data
)
81 gtk_widget_hide_all(widget
);
82 gst_element_set_state(global_pipeline
, GST_STATE_NULL
);
89 set_up_window(GstElement
*sink
, int screen_no
){
90 static const GdkColor black
= {0, 0, 0, 0};
92 GtkWidget
*window
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
93 g_signal_connect(G_OBJECT(window
), "delete-event",
94 G_CALLBACK(window_closed
), (gpointer
)sink
);
97 gtk_window_set_default_size(GTK_WINDOW(window
), WIDTH
, HEIGHT
);
99 GtkWidget
*video_window
= window
;
100 //GtkWidget *video_window = gtk_drawing_area_new();
101 //gtk_container_add(GTK_CONTAINER(window), video_window);
102 gtk_widget_set_double_buffered(video_window
, FALSE
);
103 gtk_container_set_border_width(GTK_CONTAINER(window
), 0);
106 gtk_widget_show_all(window
);
107 gtk_widget_realize(window
);
109 GdkWindow
*gdk_window
= gtk_widget_get_window(video_window
);
111 XID xid
= GDK_WINDOW_XID(gdk_window
);
112 gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(sink
), xid
);
114 /*if more than one screen is requested, set the screen position.
115 otherwise let it fall were it falls */
116 if (option_screens
> 1 || option_first_screen
){
117 /* "screen" is not the same thing as "monitor" */
118 GdkScreen
* screen
= gdk_screen_get_default();
119 int width
= gdk_screen_get_width(screen
);
120 /* XXX window selection is specific to equally sized windows arranged
121 horizontally. This could be generalised, perhaps using trial and
123 gtk_window_move(GTK_WINDOW(window
),
124 (width
/ 2 * screen_no
+ 200) % width
, 50);
126 if (option_fullscreen
){
127 gtk_window_fullscreen(GTK_WINDOW(window
));
130 gtk_widget_modify_bg(window
, GTK_STATE_NORMAL
, &black
);
131 g_signal_connect(G_OBJECT(video_window
), "key-press-event",
132 G_CALLBACK(key_press_event_cb
), NULL
);
133 g_signal_connect(G_OBJECT(window
), "destroy",
134 G_CALLBACK(window_closed
), (gpointer
)sink
);
142 gint
main (gint argc
, gchar
*argv
[])
144 //initialise threads before any gtk stuff (because not using gtk_init)
146 /*this is more complicated than plain gtk_init/gst_init, so that options from
147 all over can be gathered and presented together.
149 GOptionGroup
*gst_opts
= gst_init_get_option_group();
150 GOptionGroup
*gtk_opts
= gtk_get_option_group(TRUE
);
151 GOptionContext
*ctx
= g_option_context_new("...!");
152 g_option_context_add_main_entries(ctx
, entries
, NULL
);
153 g_option_context_add_group(ctx
, gst_opts
);
154 g_option_context_add_group(ctx
, gtk_opts
);
155 GError
*error
= NULL
;
156 if (!g_option_context_parse(ctx
, &argc
, &argv
, &error
)){
157 g_print ("Error initializing: %s\n", GST_STR_NULL(error
->message
));
160 g_option_context_free(ctx
);
162 /*get the pipeline */
163 GstElement
*sinks
[MAX_SCREENS
];
164 global_pipeline
= (GstElement
*)make_multi_pipeline(sinks
, option_screens
);
168 for (i
= 0; i
< option_screens
; i
++){
169 set_up_window(sinks
[i
], i
+ option_first_screen
);
172 GstStateChangeReturn sret
= gst_element_set_state(global_pipeline
, GST_STATE_PLAYING
);
173 if (sret
== GST_STATE_CHANGE_FAILURE
)
174 gst_element_set_state (global_pipeline
, GST_STATE_NULL
);
178 gst_object_unref(global_pipeline
);