get jpeg loading (but not reading) working
[sparrow.git] / gtk-app.c
blob4dff0b18b4a21970be3019a971458c23d0ad99d3
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 typedef struct windows_s {
14 GstElement *sinks[2];
15 XID windows[2];
16 int n;
17 } windows_t;
20 static void
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]),
29 w->windows[i]);
34 static void
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));
40 else{
41 gtk_window_fullscreen(GTK_WINDOW(widget));
46 static gboolean
47 key_press_event_cb(GtkWidget *widget, GdkEventKey *event, gpointer data)
49 g_print("got key %c\n", event->keyval);
50 switch (event->keyval){
51 case 'f':
52 toggle_fullscreen(widget);
53 break;
54 case 'q':
55 g_signal_emit_by_name(widget, "destroy");
56 break;
57 default:
58 break;
60 return TRUE;
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);
70 static void
71 video_widget_realize_cb (GtkWidget * widget, gpointer data)
73 windows_t *w = (windows_t *)data;
74 if (w->n < 2){
75 w->windows[w->n] = GDK_WINDOW_XID(GDK_WINDOW(widget->window));
77 else {
78 g_print("wtf, there seem to be %d windows!\n", w->n);
80 w->n++;
81 return;
85 static void
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[])
105 /* initialization */
106 gst_init (&argc, &argv);
107 gtk_init (&argc, &argv);
109 /* herein we count windows and map them to sinks */
110 windows_t windows;
111 windows.n = 0;
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);
141 return 0;