gtk-app gets command-line options, still crashes
[sparrow.git] / gtk-app.c
blob39df03a2912ea5139cce0da374cf4dc62efde7c5
1 /*
2 Largely based on an example by Tristan Matthews
3 http://tristanswork.blogspot.com/2008/09/fullscreen-video-in-gstreamer-with-gtk.html
5 */
6 #include <gst/gst.h>
7 #include <gtk/gtk.h>
8 #include <gst/interfaces/xoverlay.h>
9 #include <gdk/gdk.h>
10 #include <gdk/gdkx.h>
11 #include "app.h"
13 static gboolean option_fullscreen = FALSE;
14 static gint option_screens = 1;
15 static gboolean option_overlay = FALSE;
18 typedef struct windows_s {
19 GstElement *sinks[2];
20 XID windows[2];
21 int n;
22 } windows_t;
25 static void
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]),
34 w->windows[i]);
39 static void
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));
45 else{
46 gtk_window_fullscreen(GTK_WINDOW(widget));
51 static gboolean
52 key_press_event_cb(GtkWidget *widget, GdkEventKey *event, gpointer data)
54 g_print("got key %c\n", event->keyval);
55 switch (event->keyval){
56 case 'f':
57 toggle_fullscreen(widget);
58 break;
59 case 'q':
60 g_signal_emit_by_name(widget, "destroy");
61 break;
62 default:
63 break;
65 return TRUE;
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);
75 static void
76 video_widget_realize_cb (GtkWidget * widget, gpointer data)
78 windows_t *w = (windows_t *)data;
79 if (w->n < 2){
80 w->windows[w->n] = GDK_WINDOW_XID(GDK_WINDOW(widget->window));
82 else {
83 g_print("wtf, there seem to be %d windows!\n", w->n);
85 w->n++;
86 return;
90 static void
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 },
117 { NULL }
121 gint main (gint argc, gchar *argv[])
123 /* initialization */
124 gst_init (&argc, &argv);
125 //gtk_init (&argc, &argv);
127 GError *error = NULL;
128 gtk_init_with_args (&argc, &argv,
129 "options:",
130 entries,
131 NULL,
132 &error);
134 /* herein we count windows and map them to sinks */
135 windows_t windows;
136 windows.n = 0;
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);
166 return 0;