diff --git a/ChangeLog b/ChangeLog index 497864d631..8667337786 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2005-02-15 Tim-Philipp Müller + + * gst/speed/demo-mp3.c: (time_tick_cb), (main): + Display current position and track length; misc. clean-ups. + + * gst/speed/gstspeed.c: (speed_get_query_types), (speed_src_query), + (speed_init), (speed_chain): + Add query function, so that the stream length and current position + get adjusted when queried (note that current position queries may + still be wrong if the audio sink returns values based on buffer + timestamps instead of passing on the query). + 2005-02-13 Benjamin Otte * gst/audioconvert/gstaudioconvert.c: (gst_audio_convert_link), diff --git a/gst/speed/demo-mp3.c b/gst/speed/demo-mp3.c index c61f15efbd..d2144cf373 100644 --- a/gst/speed/demo-mp3.c +++ b/gst/speed/demo-mp3.c @@ -25,6 +25,8 @@ #include #include +static GtkWidget *poslabel; /* NULL */ + void set_speed (GtkAdjustment * adj, gpointer data) { @@ -33,10 +35,34 @@ set_speed (GtkAdjustment * adj, gpointer data) g_object_set (speed, "speed", adj->value, NULL); } +static gboolean +time_tick_cb (GstElement * audiosink) +{ + GstFormat format = GST_FORMAT_TIME; + guint64 total, pos; + + if (gst_element_query (audiosink, GST_QUERY_TOTAL, &format, &total) + && gst_element_query (audiosink, GST_QUERY_POSITION, &format, &pos)) { + guint t_min, t_sec, p_min, p_sec; + gchar *s; + + t_min = (guint) (total / (GST_SECOND * 60)); + t_sec = (guint) ((total % (GST_SECOND * 60)) / GST_SECOND); + p_min = (guint) (pos / (GST_SECOND * 60)); + p_sec = (guint) ((pos % (GST_SECOND * 60)) / GST_SECOND); + + s = g_strdup_printf ("%u:%02u / %u:%02u", p_min, p_sec, t_min, t_sec); + gtk_label_set_text (GTK_LABEL (poslabel), s); + g_free (s); + } + + return TRUE; /* call again */ +} + int main (int argc, char **argv) { - GtkWidget *window, *vbox, *hscale, *button; + GtkWidget *window, *vbox, *hscale, *button, *hbbox; GstElement *filesrc, *mad, *audioconvert, *speed, *audiosink, *pipeline; gst_init (&argc, &argv); @@ -48,20 +74,23 @@ main (int argc, char **argv) } window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + g_signal_connect (window, "delete-event", G_CALLBACK (gtk_main_quit), NULL); gtk_window_set_default_size (GTK_WINDOW (window), 400, 80); vbox = gtk_vbox_new (FALSE, 0); - gtk_widget_show (vbox); - hscale = gtk_hscale_new (GTK_ADJUSTMENT (gtk_adjustment_new (1.0, 0.01, 4.0, + gtk_container_set_border_width (GTK_CONTAINER (vbox), 6); + hscale = gtk_hscale_new (GTK_ADJUSTMENT (gtk_adjustment_new (1.0, 0.1, 4.0, 0.1, 0.0, 0.0))); gtk_scale_set_digits (GTK_SCALE (hscale), 2); gtk_range_set_update_policy (GTK_RANGE (hscale), GTK_UPDATE_CONTINUOUS); - button = gtk_button_new_with_label ("quit"); + hbbox = gtk_hbutton_box_new (); + button = gtk_button_new_from_stock (GTK_STOCK_QUIT); gtk_container_add (GTK_CONTAINER (window), vbox); + gtk_container_add (GTK_CONTAINER (hbbox), button); + poslabel = gtk_label_new (NULL); + gtk_box_pack_start (GTK_BOX (vbox), poslabel, FALSE, FALSE, 2); gtk_box_pack_start (GTK_BOX (vbox), hscale, TRUE, TRUE, 2); - gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 2); - gtk_widget_show (hscale); - gtk_signal_connect (GTK_OBJECT (button), "clicked", gtk_main_quit, NULL); - gtk_widget_show (button); + gtk_box_pack_start (GTK_BOX (vbox), hbbox, FALSE, FALSE, 6); + g_signal_connect (button, "clicked", G_CALLBACK (gtk_main_quit), NULL); filesrc = gst_element_factory_make ("filesrc", "filesrc"); mad = gst_element_factory_make ("mad", "mad"); @@ -69,8 +98,8 @@ main (int argc, char **argv) speed = gst_element_factory_make ("speed", "speed"); audiosink = gst_element_factory_make (DEFAULT_AUDIOSINK, "audiosink"); - gtk_signal_connect (GTK_OBJECT (gtk_range_get_adjustment (GTK_RANGE - (hscale))), "value_changed", G_CALLBACK (set_speed), speed); + g_signal_connect (gtk_range_get_adjustment (GTK_RANGE (hscale)), + "value_changed", G_CALLBACK (set_speed), speed); pipeline = gst_pipeline_new ("app"); gst_bin_add_many (GST_BIN (pipeline), filesrc, mad, audioconvert, speed, @@ -80,10 +109,15 @@ main (int argc, char **argv) gst_element_set_state (pipeline, GST_STATE_PLAYING); - gtk_widget_show (window); - gtk_idle_add ((GtkFunction) gst_bin_iterate, pipeline); + gtk_widget_show_all (window); + + g_idle_add ((GSourceFunc) gst_bin_iterate, pipeline); + g_timeout_add (200, (GSourceFunc) time_tick_cb, audiosink); gtk_main (); + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (GST_OBJECT (pipeline)); + return 0; } diff --git a/gst/speed/gstspeed.c b/gst/speed/gstspeed.c index 79b39f856a..f784c10511 100644 --- a/gst/speed/gstspeed.c +++ b/gst/speed/gstspeed.c @@ -169,6 +169,80 @@ gst_speed_get_type (void) return speed_type; } +static const GstQueryType * +speed_get_query_types (GstPad * pad) +{ + static const GstQueryType src_query_types[] = { + GST_QUERY_TOTAL, + GST_QUERY_POSITION, + 0 + }; + + return src_query_types; +} + +static gboolean +speed_src_query (GstPad * pad, GstQueryType type, + GstFormat * format, gint64 * val) +{ + gboolean res = TRUE; + GstSpeed *filter; + + filter = GST_SPEED (gst_pad_get_parent (pad)); + + switch (type) { + case GST_QUERY_POSITION: + case GST_QUERY_TOTAL: + { + switch (*format) { + case GST_FORMAT_BYTES: + case GST_FORMAT_DEFAULT: + case GST_FORMAT_TIME: + { + gint64 peer_value; + const GstFormat *peer_formats; + + res = FALSE; + + peer_formats = gst_pad_get_formats (GST_PAD_PEER (filter->sinkpad)); + + while (peer_formats && *peer_formats && !res) { + + GstFormat peer_format = *peer_formats; + + /* do the probe */ + if (gst_pad_query (GST_PAD_PEER (filter->sinkpad), type, + &peer_format, &peer_value)) { + GstFormat conv_format; + + /* convert to TIME */ + conv_format = GST_FORMAT_TIME; + res = gst_pad_convert (filter->sinkpad, + peer_format, peer_value, &conv_format, val); + + /* adjust for speed factor */ + *val = (gint64) (((gdouble) * val) / filter->speed); + + /* and to final format */ + res &= gst_pad_convert (pad, GST_FORMAT_TIME, *val, format, val); + } + peer_formats++; + } + break; + } + default: + res = FALSE; + break; + } + break; + } + default: + res = FALSE; + break; + } + return res; +} + static void speed_base_init (gpointer g_class) { @@ -214,6 +288,8 @@ speed_init (GstSpeed * filter) (&gst_speed_src_template), "src"); gst_pad_set_link_function (filter->srcpad, speed_link); gst_pad_set_getcaps_function (filter->srcpad, gst_pad_proxy_getcaps); + gst_pad_set_query_type_function (filter->srcpad, speed_get_query_types); + gst_pad_set_query_function (filter->srcpad, speed_src_query); gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad); filter->offset = 0; @@ -307,12 +383,15 @@ speed_chain (GstPad * pad, GstData * data) { gint64 timestamp, offset; + if (gst_event_discont_get_value (GST_EVENT (data), GST_FORMAT_TIME, + ×tamp)) { + filter->timestamp = timestamp; + filter->offset = timestamp * filter->rate / GST_SECOND; + } if (gst_event_discont_get_value (GST_EVENT (data), GST_FORMAT_BYTES, - ×tamp) - && gst_event_discont_get_value (GST_EVENT (data), GST_FORMAT_BYTES, &offset)) { filter->offset = offset; - filter->timestamp = timestamp; + filter->timestamp = offset * GST_SECOND / filter->rate; } break; }