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/>.
27 static GstElement
* pipeline
;
28 static gfloat scale
= 1.0;
30 #define CLEAR_OSD " \r "
33 change_speed (gfloat new_speed
)
35 g_print(CLEAR_OSD
"changing speed to: %3.2f", new_speed
);
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");
51 seek (gint seconds
, gboolean abs
)
55 new_pos
= seconds
* GST_SECOND
;
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
;
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;
80 cb_print_osd(gpointer data
) {
81 GstFormat time_format
;
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
));
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");
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)");
121 gst_message_unref (msg
);
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
);
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");
144 state
= GST_STATE_PLAYING
;
145 g_timeout_add(1000, cb_print_osd
, NULL
);
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");
159 state
= GST_STATE_PAUSED
;
164 static void key_press( GtkWidget
*widget
,
167 switch (event
->keyval
) {
172 change_speed(scale
* 1.1);
175 change_speed(scale
* 2.0);
178 change_speed(scale
* .90909);
181 change_speed(scale
* .5);
188 change_speed(scale
* -1);
210 (state
== GST_STATE_PLAYING
)?cb_pause(NULL
, NULL
):cb_play(NULL
, NULL
);
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
));
226 g_print (CLEAR_OSD
"char: %s (%i)", event
->string
, event
->keyval
);
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"))
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
)));
245 sstr
= gst_structure_to_string (s
);
246 g_print ("%s\n", sstr
);
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
);
265 pipeline
= build_pipeline (filenames
[i
], pargs
);
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
);
275 g_print("An error occured building pipeline for: %s\n", filenames
[i
]);