All plugins updated for element state changes.
[platform/upstream/gstreamer.git] / examples / seeking / cdplayer.c
1 #include <stdlib.h>
2 #include <glib.h>
3 #include <gtk/gtk.h>
4 #include <gst/gst.h>
5 #include <string.h>
6
7 static GList *seekable_elements = NULL;
8
9 static GstElement *pipeline;
10 static GtkAdjustment *adjustment;
11 static gboolean stats = FALSE;
12 static guint64 duration;
13
14 static guint update_id;
15
16 #define UPDATE_INTERVAL 500
17
18 static GstElement *
19 make_cdaudio_pipeline (void)
20 {
21   GstElement *cdaudio;
22
23   cdaudio = gst_element_factory_make ("cdaudio", "cdaudio");
24   g_assert (cdaudio != NULL);
25
26   seekable_elements = g_list_prepend (seekable_elements, cdaudio);
27
28   return cdaudio;
29 }
30
31 static gchar *
32 format_value (GtkScale * scale, gdouble value)
33 {
34   gint64 real;
35   gint64 seconds;
36   gint64 subseconds;
37
38   real = value * duration / 100;
39   seconds = (gint64) real / GST_SECOND;
40   subseconds = (gint64) real / (GST_SECOND / 100);
41
42   return g_strdup_printf ("%02" G_GINT64_FORMAT ":%02" G_GINT64_FORMAT ":%02"
43       G_GINT64_FORMAT, seconds / 60, seconds % 60, subseconds % 100);
44 }
45
46 typedef struct
47 {
48   const gchar *name;
49   const GstFormat format;
50 }
51 seek_format;
52
53 static seek_format seek_formats[] = {
54   {"tim", GST_FORMAT_TIME},
55   {"byt", GST_FORMAT_BYTES},
56   {"buf", GST_FORMAT_BUFFERS},
57   {"def", GST_FORMAT_DEFAULT},
58   {NULL, 0},
59 };
60
61
62 G_GNUC_UNUSED static void
63 query_durations ()
64 {
65   GList *walk = seekable_elements;
66
67   while (walk) {
68     GstElement *element = GST_ELEMENT (walk->data);
69     gint i = 0;
70
71     g_print ("durations %8.8s: ", GST_ELEMENT_NAME (element));
72     while (seek_formats[i].name) {
73       gboolean res;
74       gint64 value;
75       GstFormat format;
76
77       format = seek_formats[i].format;
78       res = gst_element_query (element, GST_QUERY_TOTAL, &format, &value);
79       if (res) {
80         g_print ("%s %13" G_GINT64_FORMAT " | ", seek_formats[i].name, value);
81       } else {
82         g_print ("%s %13.13s | ", seek_formats[i].name, "*NA*");
83       }
84       i++;
85     }
86     g_print (" %s\n", GST_ELEMENT_NAME (element));
87     walk = g_list_next (walk);
88   }
89 }
90
91 G_GNUC_UNUSED static void
92 query_positions ()
93 {
94   GList *walk = seekable_elements;
95
96   while (walk) {
97     GstElement *element = GST_ELEMENT (walk->data);
98     gint i = 0;
99
100     g_print ("positions %8.8s: ", GST_ELEMENT_NAME (element));
101     while (seek_formats[i].name) {
102       gboolean res;
103       gint64 value;
104       GstFormat format;
105
106       format = seek_formats[i].format;
107       res = gst_element_query (element, GST_QUERY_POSITION, &format, &value);
108       if (res) {
109         g_print ("%s %13" G_GINT64_FORMAT " | ", seek_formats[i].name, value);
110       } else {
111         g_print ("%s %13.13s | ", seek_formats[i].name, "*NA*");
112       }
113       i++;
114     }
115     g_print (" %s\n", GST_ELEMENT_NAME (element));
116     walk = g_list_next (walk);
117   }
118 }
119
120 static gboolean
121 update_scale (gpointer data)
122 {
123   GstClock *clock;
124   guint64 position = 0;
125   GstFormat format = GST_FORMAT_TIME;
126
127   duration = 0;
128   clock = gst_pipeline_get_clock (GST_PIPELINE (pipeline));
129
130   if (seekable_elements) {
131     GstElement *element = GST_ELEMENT (seekable_elements->data);
132
133     gst_element_query (element, GST_QUERY_TOTAL, &format, &duration);
134     gst_element_query (element, GST_QUERY_POSITION, &format, &position);
135   }
136
137   if (stats) {
138     if (clock)
139       g_print ("clock:                  %13" G_GUINT64_FORMAT "  (%s)\n",
140           position, gst_object_get_name (GST_OBJECT (clock)));
141     query_durations ();
142     query_positions ();
143   }
144   if (duration > 0) {
145     gtk_adjustment_set_value (adjustment, position * 100.0 / duration);
146   }
147
148   return TRUE;
149 }
150
151 static gboolean
152 start_seek (GtkWidget * widget, GdkEventButton * event, gpointer user_data)
153 {
154   gst_element_set_state (pipeline, GST_STATE_PAUSED);
155   gtk_timeout_remove (update_id);
156
157   return FALSE;
158 }
159
160 static gboolean
161 stop_seek (GtkWidget * widget, GdkEventButton * event, gpointer user_data)
162 {
163   gint64 real = gtk_range_get_value (GTK_RANGE (widget)) * duration / 100;
164   gboolean res;
165   GstEvent *s_event;
166   GList *walk = seekable_elements;
167
168   while (walk) {
169     GstElement *seekable = GST_ELEMENT (walk->data);
170
171     g_print ("seek to %" G_GINT64_FORMAT " on element %s\n", real,
172         GST_ELEMENT_NAME (seekable));
173     s_event =
174         gst_event_new_seek (GST_FORMAT_TIME | GST_SEEK_METHOD_SET |
175         GST_SEEK_FLAG_FLUSH, real);
176
177     res = gst_element_send_event (seekable, s_event);
178
179     walk = g_list_next (walk);
180   }
181
182   gst_element_set_state (pipeline, GST_STATE_PLAYING);
183   update_id =
184       gtk_timeout_add (UPDATE_INTERVAL, (GtkFunction) update_scale, pipeline);
185
186   return FALSE;
187 }
188
189 static void
190 play_cb (GtkButton * button, gpointer data)
191 {
192   GstState state;
193
194   gst_element_get_state (pipeline, &state, NULL, NULL);
195   if (state != GST_STATE_PLAYING) {
196     gst_element_set_state (pipeline, GST_STATE_PLAYING);
197     update_id =
198         gtk_timeout_add (UPDATE_INTERVAL, (GtkFunction) update_scale, pipeline);
199   }
200 }
201
202 static void
203 pause_cb (GtkButton * button, gpointer data)
204 {
205   GstState state;
206
207   gst_element_get_state (pipeline, &state, NULL, NULL);
208   if (state != GST_STATE_PAUSED) {
209     gst_element_set_state (pipeline, GST_STATE_PAUSED);
210     gtk_timeout_remove (update_id);
211   }
212 }
213
214 static void
215 stop_cb (GtkButton * button, gpointer data)
216 {
217   GstState state;
218
219   gst_element_get_state (pipeline, &state, NULL, NULL);
220   if (state != GST_STATE_READY) {
221     gst_element_set_state (pipeline, GST_STATE_READY);
222     gtk_timeout_remove (update_id);
223   }
224 }
225
226 int
227 main (int argc, char **argv)
228 {
229   GtkWidget *window, *hbox, *vbox,
230       *play_button, *pause_button, *stop_button, *hscale;
231   struct poptOption options[] = {
232     {"stats", 's', POPT_ARG_NONE | POPT_ARGFLAG_STRIP, &stats, 0,
233         "Show element stats", NULL},
234     POPT_TABLEEND
235   };
236
237   gst_init_with_popt_table (&argc, &argv, options);
238   gtk_init (&argc, &argv);
239
240   pipeline = make_cdaudio_pipeline ();
241
242   g_signal_connect (pipeline, "deep_notify",
243       G_CALLBACK (gst_object_default_deep_notify), NULL);
244
245   /* initialize gui elements ... */
246   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
247   hbox = gtk_hbox_new (FALSE, 0);
248   vbox = gtk_vbox_new (FALSE, 0);
249   play_button = gtk_button_new_with_label ("play");
250   pause_button = gtk_button_new_with_label ("pause");
251   stop_button = gtk_button_new_with_label ("stop");
252
253   adjustment =
254       GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.00, 100.0, 0.1, 1.0, 1.0));
255   hscale = gtk_hscale_new (adjustment);
256   gtk_scale_set_digits (GTK_SCALE (hscale), 2);
257   gtk_range_set_update_policy (GTK_RANGE (hscale), GTK_UPDATE_CONTINUOUS);
258
259   gtk_signal_connect (GTK_OBJECT (hscale),
260       "button_press_event", G_CALLBACK (start_seek), pipeline);
261   gtk_signal_connect (GTK_OBJECT (hscale),
262       "button_release_event", G_CALLBACK (stop_seek), pipeline);
263   gtk_signal_connect (GTK_OBJECT (hscale),
264       "format_value", G_CALLBACK (format_value), pipeline);
265
266   /* do the packing stuff ... */
267   gtk_window_set_default_size (GTK_WINDOW (window), 96, 96);
268   gtk_container_add (GTK_CONTAINER (window), vbox);
269   gtk_container_add (GTK_CONTAINER (vbox), hbox);
270   gtk_box_pack_start (GTK_BOX (hbox), play_button, FALSE, FALSE, 2);
271   gtk_box_pack_start (GTK_BOX (hbox), pause_button, FALSE, FALSE, 2);
272   gtk_box_pack_start (GTK_BOX (hbox), stop_button, FALSE, FALSE, 2);
273   gtk_box_pack_start (GTK_BOX (vbox), hscale, TRUE, TRUE, 2);
274
275   /* connect things ... */
276   g_signal_connect (G_OBJECT (play_button), "clicked", G_CALLBACK (play_cb),
277       pipeline);
278   g_signal_connect (G_OBJECT (pause_button), "clicked", G_CALLBACK (pause_cb),
279       pipeline);
280   g_signal_connect (G_OBJECT (stop_button), "clicked", G_CALLBACK (stop_cb),
281       pipeline);
282   g_signal_connect (G_OBJECT (window), "delete_event", gtk_main_quit, NULL);
283
284   /* show the gui. */
285   gtk_widget_show_all (window);
286
287   gtk_main ();
288
289   gst_element_set_state (pipeline, GST_STATE_NULL);
290
291   return 0;
292 }