add gui
[gst-scaletempo-demo-rj.git] / src / gui.c
bloba42d004004f6f7068955a6238450e5ba03ed9412
1 /* gui.c
2 * Copyright (C) 2008 Rov Juvano <rovjuvano@users.sourceforge.net>
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
22 #include <string.h>
23 #include <gtk/gtk.h>
24 #include "play.h"
25 #include "gui.h"
27 static GstElement * pipeline;
28 static gfloat scale = 1.0;
30 #define CLEAR_OSD " \r "
32 static void
33 change_speed (gfloat new_speed)
35 g_print(CLEAR_OSD "changing speed to: %3.2f", new_speed);
36 scale = new_speed;
37 gint64 pos;
38 GstFormat fmt = GST_FORMAT_TIME;
39 if ( !gst_element_query_position (pipeline, &fmt, &pos) ) {
40 g_print ("position query failed!\n");
42 if (!gst_element_seek (pipeline, scale,
43 GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH,
44 GST_SEEK_TYPE_SET, pos,
45 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) {
46 g_print ("speed change failed!\n");
50 static void
51 seek (gint seconds, gboolean abs)
53 gint64 new_pos;
54 if (abs) {
55 new_pos = seconds * GST_SECOND;
56 } else {
57 gint64 pos;
58 GstFormat fmt = GST_FORMAT_TIME;
59 if ( !gst_element_query_position (pipeline, &fmt, &pos) ) {
60 g_print ("position query failed!\n");
62 new_pos = pos + seconds * GST_SECOND;
64 if (new_pos < 0)
65 new_pos = 0;
66 g_print (CLEAR_OSD "seeking: %3i seconds to %" GST_TIME_FORMAT,
67 seconds, GST_TIME_ARGS(new_pos));
68 if (!gst_element_seek (pipeline, scale,
69 GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH,
70 GST_SEEK_TYPE_SET, new_pos,
71 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) {
72 g_print ("seek failed!\n");
76 static GstState state = GST_STATE_NULL;
78 static int stop_osd = 0;
79 int
80 cb_print_osd(gpointer data) {
81 GstFormat time_format;
82 gint64 dur, pos;
83 gchar *filename = (gchar *)data;
85 time_format = GST_FORMAT_TIME;
86 if (gst_element_query_duration (pipeline, &time_format, &dur) &&
87 gst_element_query_position (pipeline, &time_format, &pos)) {
88 g_print ("\r %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT,
89 GST_TIME_ARGS (pos), GST_TIME_ARGS (dur));
90 } else {
91 g_print ("\r Could not read position and duration");
94 GstBus * bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
95 gst_object_unref (bus);
96 GstMessage *msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, 0);
97 if (msg && GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR)
98 goto got_error_message;
99 if (msg && GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS) {
100 g_print ("Finished.\n");
101 return 0;
104 if (stop_osd) {
105 stop_osd = 0;
106 return 0;
108 return 1;
110 got_error_message:
112 if (msg) {
113 GError *err = NULL;
114 gchar *dbg_str = NULL;
116 gst_message_parse_error (msg, &err, &dbg_str);
117 g_printerr ("FAILED to play %s: %s\n%s\n", filename, err->message,
118 (dbg_str) ? dbg_str : "(no debugging information)");
119 g_error_free (err);
120 g_free (dbg_str);
121 gst_message_unref (msg);
122 } else {
123 g_printerr ("FAILED to play %s: unknown error\n", filename);
126 /* shut down and free everything */
127 gst_element_set_state (pipeline, GST_STATE_NULL);
128 gst_object_unref (pipeline);
129 gst_object_unref (bus);
130 return 0;
134 static void
135 cb_play (GtkButton * button, gpointer data)
137 if (state != GST_STATE_PLAYING) {
138 g_print (CLEAR_OSD "PLAY pipeline");
139 GstStateChangeReturn ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
140 if (ret == GST_STATE_CHANGE_FAILURE) {
141 g_print ("PLAY failed\n");
142 return;
144 state = GST_STATE_PLAYING;
145 g_timeout_add(1000, cb_print_osd, NULL);
149 static void
150 cb_pause (GtkButton * button, gpointer data)
152 if (state != GST_STATE_PAUSED) {
153 g_print (CLEAR_OSD "PAUSE pipeline");
154 GstStateChangeReturn ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
155 if (ret == GST_STATE_CHANGE_FAILURE) {
156 g_print ("PAUSE failed\n");
157 return;
159 state = GST_STATE_PAUSED;
160 stop_osd = 1;
164 static void key_press( GtkWidget *widget,
165 GdkEventKey *event )
167 switch (event->keyval) {
168 case 'q':
169 gtk_main_quit ();
170 break;
171 case ']':
172 change_speed(scale * 1.1);
173 break;
174 case '}':
175 change_speed(scale * 2.0);
176 break;
177 case '[':
178 change_speed(scale * .90909);
179 break;
180 case '{':
181 change_speed(scale * .5);
182 break;
183 case 65288:
184 case '|':
185 change_speed(1.0);
186 break;
187 case '-':
188 change_speed(scale * -1);
189 break;
190 case 65361:
191 case 'j':
192 seek(-5, FALSE);
193 break;
194 case 65363:
195 case 'k':
196 seek(5, FALSE);
197 break;
198 case 65364:
199 case 'J':
200 seek(-30, FALSE);
201 break;
202 case 65362:
203 case 'K':
204 seek(30, FALSE);
205 break;
206 case '0':
207 seek(0, TRUE);
208 break;
209 case ' ':
210 (state == GST_STATE_PLAYING)?cb_pause(NULL, NULL):cb_play(NULL, NULL);
211 break;
212 case 65293:
213 case '\n':
214 case '\r':
215 case '\f': {
216 seek(0, FALSE);
217 gint64 pos;
218 GstFormat fmt = GST_FORMAT_TIME;
219 if ( !gst_element_query_position (pipeline, &fmt, &pos) ) {
220 g_print ("position query failed!\n");
222 g_print (CLEAR_OSD "\r%" GST_TIME_FORMAT "", GST_TIME_ARGS(pos));
223 break;
225 default:
226 g_print (CLEAR_OSD "char: %s (%i)", event->string, event->keyval);
230 static void
231 message_received (GstBus * bus, GstMessage * message, GstPipeline * pipeline)
233 const GstStructure *s;
235 s = gst_message_get_structure (message);
236 const char * type = gst_message_type_get_name (GST_MESSAGE_TYPE (message));
237 if (!strcmp(type, "state-changed") && strcmp(GST_ELEMENT_NAME (GST_MESSAGE_SRC (message)), "my-pipeline"))
238 return;
239 g_print ("\rmessage from \"%s\" (%s): ",
240 GST_STR_NULL (GST_ELEMENT_NAME (GST_MESSAGE_SRC (message))),
241 gst_message_type_get_name (GST_MESSAGE_TYPE (message)));
242 if (s) {
243 gchar *sstr;
245 sstr = gst_structure_to_string (s);
246 g_print ("%s\n", sstr);
247 g_free (sstr);
248 } else {
249 g_print ("no message details\n");
253 void lauch_gui (int argc, char *argv[], gchar **filenames, pipeline_args * pargs)
255 gtk_init (&argc, &argv);
256 GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
257 gtk_window_set_default_size (GTK_WINDOW (window), 640, 360);
258 gtk_widget_set_events (window, GDK_KEY_PRESS_MASK);
259 gtk_signal_connect (GTK_OBJECT (window), "key_press_event",
260 (GtkSignalFunc) key_press, NULL);
261 gtk_widget_show (window);
263 gint i=0;
265 pipeline = build_pipeline (filenames[i], pargs);
266 if (pipeline) {
267 //play(pipeline, filenames[i]);
268 GstBus * bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
269 gst_object_unref (bus);
271 g_signal_connect (bus, "message::", (GCallback) message_received, pipeline);
273 cb_play(NULL, NULL);
274 } else {
275 g_print("An error occured building pipeline for: %s\n", filenames[i]);
278 gtk_main ();