diff --git a/ChangeLog b/ChangeLog index 67d74ae9f8..ceedb95b7e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2006-05-07 Stefan Kost + + * gst/adder/gstadder.c: (gst_adder_sink_event), + (gst_adder_request_new_pad), (gst_adder_change_state): + * gst/adder/gstadder.h: + * tests/check/Makefile.am: + * tests/check/elements/adder.c: (event_loop), (GST_START_TEST), + (adder_suite), (main): + Add sink-event handling to adder. It tries to merge incomming + newsegment-events. Added test to check if segment_done is comming + through. + 2006-05-05 Andy Wingo * ext/theora/theoraparse.c (gst_theora_parse_init) diff --git a/gst/adder/gstadder.c b/gst/adder/gstadder.c index 5362d3fbf8..3b713dffb2 100644 --- a/gst/adder/gstadder.c +++ b/gst/adder/gstadder.c @@ -91,6 +91,7 @@ static void gst_adder_dispose (GObject * object); static gboolean gst_adder_setcaps (GstPad * pad, GstCaps * caps); static gboolean gst_adder_query (GstPad * pad, GstQuery * query); static gboolean gst_adder_src_event (GstPad * pad, GstEvent * event); +static gboolean gst_adder_sink_event (GstPad * pad, GstEvent * event); static GstPad *gst_adder_request_new_pad (GstElement * element, GstPadTemplate * temp, const gchar * unused); @@ -292,6 +293,67 @@ gst_adder_src_event (GstPad * pad, GstEvent * event) return result; } +static gboolean +gst_adder_sink_event (GstPad * pad, GstEvent * event) +{ + GstAdder *adder; + gboolean ret; + + adder = GST_ADDER (gst_pad_get_parent (pad)); + + GST_DEBUG ("Got %s event on pad %s:%s", GST_EVENT_TYPE_NAME (event), + GST_DEBUG_PAD_NAME (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_NEWSEGMENT: + { + gint64 start, stop, time; + gdouble rate; + GstFormat format; + gboolean update; + gboolean change = FALSE; + + gst_event_parse_new_segment (event, &update, &rate, &format, + &start, &stop, &time); + + GST_DEBUG_OBJECT (pad, "got newsegment, start %" GST_TIME_FORMAT + ", stop %" GST_TIME_FORMAT, GST_TIME_ARGS (start), + GST_TIME_ARGS (stop)); + + if (adder->segment.format != format) { + gst_segment_init (&adder->segment, format); + change = TRUE; + } else if ((adder->segment.rate != rate) + || (adder->segment.format != format) + || (adder->segment.start != start) + || (adder->segment.stop != stop) + || (adder->segment.time != time)) { + change = TRUE; + } + if (change) { + GST_DEBUG ("Send new newsegment"); + gst_segment_set_newsegment (&adder->segment, update, rate, format, + start, stop, time); + + /* send new newsegment event */ + gst_pad_push_event (adder->srcpad, + gst_event_new_new_segment (update, rate, format, start, stop, + time)); + /* gst_event_unref (event); */ + } + break; + } + default: + break; + } + + /* now GstCollectPads can take care of the rest, e.g. EOS */ + ret = adder->collect_event (pad, event); + + gst_object_unref (adder); + return ret; +} + static void gst_adder_class_init (GstAdderClass * klass) { @@ -375,6 +437,13 @@ gst_adder_request_new_pad (GstElement * element, GstPadTemplate * templ, GST_DEBUG_FUNCPTR (gst_pad_proxy_getcaps)); gst_pad_set_setcaps_function (newpad, GST_DEBUG_FUNCPTR (gst_adder_setcaps)); gst_collect_pads_add_pad (adder->collect, newpad, sizeof (GstCollectData)); + + /* FIXME: hacked way to override/extend the event function of + * GstCollectPads; because it sets its own event function giving the + * element no access to events */ + adder->collect_event = (GstPadEventFunction) GST_PAD_EVENTFUNC (newpad); + gst_pad_set_event_function (newpad, GST_DEBUG_FUNCPTR (gst_adder_sink_event)); + if (!gst_element_add_pad (GST_ELEMENT (adder), newpad)) goto could_not_add; @@ -513,6 +582,7 @@ gst_adder_change_state (GstElement * element, GstStateChange transition) case GST_STATE_CHANGE_READY_TO_PAUSED: adder->timestamp = 0; adder->offset = 0; + gst_segment_init (&adder->segment, GST_FORMAT_UNDEFINED); gst_collect_pads_start (adder->collect); break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING: diff --git a/gst/adder/gstadder.h b/gst/adder/gstadder.h index 81b6af9621..f91ffd2417 100644 --- a/gst/adder/gstadder.h +++ b/gst/adder/gstadder.h @@ -28,16 +28,12 @@ G_BEGIN_DECLS -#define GST_TYPE_ADDER \ - (gst_adder_get_type()) -#define GST_ADDER(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ADDER,GstAdder)) -#define GST_ADDER_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ADDER,GstAdderClass)) -#define GST_IS_ADDER(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ADDER)) -#define GST_IS_ADDER_CLASS(obj) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ADDER)) +#define GST_TYPE_ADDER (gst_adder_get_type()) +#define GST_ADDER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ADDER,GstAdder)) +#define GST_IS_ADDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ADDER)) +#define GST_ADDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_ADDER,GstAdderClass)) +#define GST_IS_ADDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_ADDER)) +#define GST_ADDER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_ADDER,GstAdderClass)) typedef struct _GstAdder GstAdder; typedef struct _GstAdderClass GstAdderClass; @@ -75,6 +71,10 @@ struct _GstAdder { /* counters to keep track of timestamps */ gint64 timestamp; gint64 offset; + + /* sink event handling */ + GstPadEventFunction collect_event; + GstSegment segment; }; struct _GstAdderClass { diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am index 9c36b47aaf..33a7fd6485 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -35,6 +35,7 @@ endif check_PROGRAMS = $(check_vorbis) \ $(check_theora) \ + elements/adder \ elements/audioconvert \ elements/audioresample \ elements/audiotestsrc \ diff --git a/tests/check/elements/adder.c b/tests/check/elements/adder.c new file mode 100644 index 0000000000..2abdf143b7 --- /dev/null +++ b/tests/check/elements/adder.c @@ -0,0 +1,156 @@ +/* GStreamer + * + * unit test for volume + * + * Copyright (C) <2005> Thomas Vander Stichele + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +#include + +static GstFormat format = GST_FORMAT_UNDEFINED; +static gint64 position = -1; + +static void +event_loop (GstElement * bin) +{ + GstBus *bus; + GstMessage *message = NULL; + GstObject *object; + GstState oldstate, newstate, pending; + gboolean loop = TRUE; + + bus = gst_element_get_bus (GST_ELEMENT (bin)); + + while (loop) { + message = gst_bus_poll (bus, GST_MESSAGE_ANY, -1); + + g_assert (message != NULL); + object = GST_MESSAGE_SRC (message); + + GST_INFO ("bus message from \"%s\" (%s): ", + GST_STR_NULL (GST_ELEMENT_NAME (object)), + gst_message_type_get_name (GST_MESSAGE_TYPE (message))); + + switch (message->type) { + case GST_MESSAGE_EOS: + loop = FALSE; + break; + case GST_MESSAGE_SEGMENT_DONE: + gst_message_parse_segment_done (message, &format, &position); + GST_INFO ("received segment_done : %" G_GINT64_FORMAT, position); + gst_element_set_state (bin, GST_STATE_NULL); + loop = FALSE; + break; + case GST_MESSAGE_WARNING: + case GST_MESSAGE_ERROR:{ + GError *gerror; + gchar *debug; + + gst_message_parse_error (message, &gerror, &debug); + gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug); + g_error_free (gerror); + g_free (debug); + return; + } + default: + break; + } + gst_message_unref (message); + } +} + + +GST_START_TEST (test_event) +{ + GstElement *bin, *src1, *src2, *adder, *sink; + GstEvent *seek_event; + gboolean res; + + /* build pipeline */ + bin = gst_pipeline_new ("pipeline"); + src1 = gst_element_factory_make ("audiotestsrc", "src1"); + g_object_set (src1, "wave", 4, NULL); /* silence */ + src2 = gst_element_factory_make ("audiotestsrc", "src2"); + g_object_set (src2, "wave", 4, NULL); /* silence */ + adder = gst_element_factory_make ("adder", "adder"); + sink = gst_element_factory_make ("fakesink", "sink"); + gst_bin_add_many (GST_BIN (bin), src1, src2, adder, sink, NULL); + + res = gst_element_link (src1, adder); + fail_unless (res == TRUE, NULL); + res = gst_element_link (src2, adder); + fail_unless (res == TRUE, NULL); + res = gst_element_link (adder, sink); + fail_unless (res == TRUE, NULL); + + seek_event = gst_event_new_seek (1.0, GST_FORMAT_TIME, + GST_SEEK_FLAG_SEGMENT, + GST_SEEK_TYPE_SET, (GstClockTime) 0, + GST_SEEK_TYPE_SET, (GstClockTime) GST_SECOND); + + /* prepare playing */ + res = gst_element_set_state (bin, GST_STATE_PAUSED); + fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL); + + res = gst_element_send_event (bin, seek_event); + fail_unless (res == TRUE, NULL); + + /* run pipeline */ + res = gst_element_set_state (bin, GST_STATE_PLAYING); + fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL); + + event_loop (bin); + + fail_unless (position == GST_SECOND, NULL); + + /* cleanup */ + gst_object_unref (G_OBJECT (bin)); +} + +GST_END_TEST; + +Suite * +adder_suite (void) +{ + Suite *s = suite_create ("adder"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_event); + + return s; +} + +int +main (int argc, char **argv) +{ + int nf; + + Suite *s = adder_suite (); + SRunner *sr = srunner_create (s); + + gst_check_init (&argc, &argv); + + srunner_run_all (sr, CK_NORMAL); + nf = srunner_ntests_failed (sr); + srunner_free (sr); + + return nf; +}