Move core plugins out of core. I don't mind fdsrc/fdsink going back into the core...
authorDavid Schleef <ds@schleef.org>
Sun, 15 May 2005 23:06:37 +0000 (23:06 +0000)
committerDavid Schleef <ds@schleef.org>
Sun, 15 May 2005 23:06:37 +0000 (23:06 +0000)
Original commit message from CVS:
Move core plugins out of core.  I don't mind fdsrc/fdsink
going back into the core; they were just disabled there, so
I moved them.  Some of this stuff could (should) be deleted.
* gst/oldcore/Makefile.am:
* gst/oldcore/gstaggregator.c:
* gst/oldcore/gstaggregator.h:
* gst/oldcore/gstelements.c:
* gst/oldcore/gstfdsink.c:
* gst/oldcore/gstfdsink.h:
* gst/oldcore/gstfdsrc.c:
* gst/oldcore/gstfdsrc.h:
* gst/oldcore/gstmd5sink.c:
* gst/oldcore/gstmd5sink.h:
* gst/oldcore/gstmultifilesrc.c:
* gst/oldcore/gstmultifilesrc.h:
* gst/oldcore/gstpipefilter.c:
* gst/oldcore/gstpipefilter.h:
* gst/oldcore/gstshaper.c:
* gst/oldcore/gstshaper.h:
* gst/oldcore/gststatistics.c:
* gst/oldcore/gststatistics.h:

17 files changed:
ChangeLog
gst/oldcore/Makefile.am [new file with mode: 0644]
gst/oldcore/gstaggregator.c [new file with mode: 0644]
gst/oldcore/gstaggregator.h [new file with mode: 0644]
gst/oldcore/gstelements.c [new file with mode: 0644]
gst/oldcore/gstfdsink.c [new file with mode: 0644]
gst/oldcore/gstfdsink.h [new file with mode: 0644]
gst/oldcore/gstmd5sink.c [new file with mode: 0644]
gst/oldcore/gstmd5sink.h [new file with mode: 0644]
gst/oldcore/gstmultifilesrc.c [new file with mode: 0644]
gst/oldcore/gstmultifilesrc.h [new file with mode: 0644]
gst/oldcore/gstpipefilter.c [new file with mode: 0644]
gst/oldcore/gstpipefilter.h [new file with mode: 0644]
gst/oldcore/gstshaper.c [new file with mode: 0644]
gst/oldcore/gstshaper.h [new file with mode: 0644]
gst/oldcore/gststatistics.c [new file with mode: 0644]
gst/oldcore/gststatistics.h [new file with mode: 0644]

index 6df95b1..f7c1742 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,27 @@
+2005-05-15  David Schleef  <ds@schleef.org>
+
+       Move core plugins out of core.  I don't mind fdsrc/fdsink
+       going back into the core; they were just disabled there, so
+       I moved them.  Some of this stuff could (should) be deleted.
+       * gst/oldcore/Makefile.am:
+       * gst/oldcore/gstaggregator.c:
+       * gst/oldcore/gstaggregator.h:
+       * gst/oldcore/gstelements.c:
+       * gst/oldcore/gstfdsink.c:
+       * gst/oldcore/gstfdsink.h:
+       * gst/oldcore/gstfdsrc.c:
+       * gst/oldcore/gstfdsrc.h:
+       * gst/oldcore/gstmd5sink.c:
+       * gst/oldcore/gstmd5sink.h:
+       * gst/oldcore/gstmultifilesrc.c:
+       * gst/oldcore/gstmultifilesrc.h:
+       * gst/oldcore/gstpipefilter.c:
+       * gst/oldcore/gstpipefilter.h:
+       * gst/oldcore/gstshaper.c:
+       * gst/oldcore/gstshaper.h:
+       * gst/oldcore/gststatistics.c:
+       * gst/oldcore/gststatistics.h:
+
 2005-05-13  Christian Schaller  <uraeus@gnome.org>
 
        * ext/Makefile.am: dist esd directory
diff --git a/gst/oldcore/Makefile.am b/gst/oldcore/Makefile.am
new file mode 100644 (file)
index 0000000..c871c87
--- /dev/null
@@ -0,0 +1,29 @@
+
+plugin_LTLIBRARIES = libgstoldcoreelements.la
+
+libgstoldcoreelements_la_SOURCES =     \
+       gstelements.c           \
+       gstaggregator.c         \
+       gstfdsink.c             \
+       gstfdsrc.c              \
+       gstmd5sink.c            \
+       gstmultifilesrc.c       \
+       gstpipefilter.c         \
+       gstshaper.c             \
+       gststatistics.c
+
+
+libgstoldcoreelements_la_CFLAGS = $(GST_CFLAGS)
+libgstoldcoreelements_la_LIBADD =
+libgstoldcoreelements_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+
+noinst_HEADERS =               \
+       gstaggregator.h         \
+       gstfdsink.h             \
+       gstfdsrc.h              \
+       gstmd5sink.h            \
+       gstmultifilesrc.h       \
+       gstpipefilter.h         \
+       gstshaper.h             \
+       gststatistics.h
+
diff --git a/gst/oldcore/gstaggregator.c b/gst/oldcore/gstaggregator.c
new file mode 100644 (file)
index 0000000..ddd806c
--- /dev/null
@@ -0,0 +1,379 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ *                    2000 Wim Taymans <wim.taymans@chello.be>
+ *
+ * gstaggregator.c: Aggregator element, N in 1 out
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include "gstaggregator.h"
+
+static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS_ANY);
+
+GST_DEBUG_CATEGORY_STATIC (gst_aggregator_debug);
+#define GST_CAT_DEFAULT gst_aggregator_debug
+
+GstElementDetails gst_aggregator_details =
+GST_ELEMENT_DETAILS ("Aggregator pipe fitting",
+    "Generic",
+    "N-to-1 pipe fitting",
+    "Wim Taymans <wim.taymans@chello.be>");
+
+/* Aggregator signals and args */
+enum
+{
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+enum
+{
+  ARG_0,
+  ARG_NUM_PADS,
+  ARG_SILENT,
+  ARG_SCHED,
+  ARG_LAST_MESSAGE
+      /* FILL ME */
+};
+
+GstStaticPadTemplate aggregator_src_template =
+GST_STATIC_PAD_TEMPLATE ("sink%d",
+    GST_PAD_SINK,
+    GST_PAD_REQUEST,
+    GST_STATIC_CAPS_ANY);
+
+#define GST_TYPE_AGGREGATOR_SCHED (gst_aggregator_sched_get_type())
+static GType
+gst_aggregator_sched_get_type (void)
+{
+  static GType aggregator_sched_type = 0;
+  static GEnumValue aggregator_sched[] = {
+    {AGGREGATOR_LOOP, "1", "Loop Based"},
+    {AGGREGATOR_LOOP_SELECT, "3", "Loop Based Select"},
+    {AGGREGATOR_CHAIN, "4", "Chain Based"},
+    {0, NULL, NULL},
+  };
+
+  if (!aggregator_sched_type) {
+    aggregator_sched_type =
+        g_enum_register_static ("GstAggregatorSched", aggregator_sched);
+  }
+  return aggregator_sched_type;
+}
+
+#define AGGREGATOR_IS_LOOP_BASED(ag)   ((ag)->sched != AGGREGATOR_CHAIN)
+
+static GstPad *gst_aggregator_request_new_pad (GstElement * element,
+    GstPadTemplate * temp, const gchar * unused);
+static void gst_aggregator_update_functions (GstAggregator * aggregator);
+
+static void gst_aggregator_finalize (GObject * object);
+static void gst_aggregator_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_aggregator_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+
+static void gst_aggregator_chain (GstPad * pad, GstData * _data);
+static void gst_aggregator_loop (GstElement * element);
+
+#define _do_init(bla) \
+  GST_DEBUG_CATEGORY_INIT (gst_aggregator_debug, "aggregator", 0, "aggregator element");
+
+GST_BOILERPLATE_FULL (GstAggregator, gst_aggregator, GstElement,
+    GST_TYPE_ELEMENT, _do_init);
+
+static void
+gst_aggregator_base_init (gpointer g_class)
+{
+  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&aggregator_src_template));
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&srctemplate));
+  gst_element_class_set_details (gstelement_class, &gst_aggregator_details);
+}
+
+static void
+gst_aggregator_finalize (GObject * object)
+{
+  GstAggregator *aggregator;
+
+  aggregator = GST_AGGREGATOR (object);
+
+  g_list_free (aggregator->sinkpads);
+  g_free (aggregator->last_message);
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gst_aggregator_class_init (GstAggregatorClass * klass)
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+
+  gobject_class = (GObjectClass *) klass;
+  gstelement_class = (GstElementClass *) klass;
+
+  gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_aggregator_set_property);
+  gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_aggregator_get_property);
+
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NUM_PADS,
+      g_param_spec_int ("num_pads", "Num pads", "The number of source pads",
+          0, G_MAXINT, 0, G_PARAM_READABLE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SILENT,
+      g_param_spec_boolean ("silent", "Silent", "Don't produce messages",
+          FALSE, G_PARAM_READWRITE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SCHED,
+      g_param_spec_enum ("sched", "Scheduling",
+          "The type of scheduling this element should use",
+          GST_TYPE_AGGREGATOR_SCHED, AGGREGATOR_CHAIN, G_PARAM_READWRITE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
+      g_param_spec_string ("last_message", "Last message",
+          "The current state of the element", NULL, G_PARAM_READABLE));
+
+  gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_aggregator_finalize);
+
+  gstelement_class->request_new_pad =
+      GST_DEBUG_FUNCPTR (gst_aggregator_request_new_pad);
+}
+
+static void
+gst_aggregator_init (GstAggregator * aggregator)
+{
+  aggregator->srcpad =
+      gst_pad_new_from_template (gst_static_pad_template_get (&srctemplate),
+      "src");
+  gst_pad_set_getcaps_function (aggregator->srcpad, gst_pad_proxy_getcaps);
+  gst_element_add_pad (GST_ELEMENT (aggregator), aggregator->srcpad);
+
+  aggregator->numsinkpads = 0;
+  aggregator->sinkpads = NULL;
+  aggregator->silent = FALSE;
+  aggregator->sched = AGGREGATOR_LOOP;
+  aggregator->last_message = NULL;
+
+  gst_aggregator_update_functions (aggregator);
+}
+
+static GstPad *
+gst_aggregator_request_new_pad (GstElement * element, GstPadTemplate * templ,
+    const gchar * unused)
+{
+  gchar *name;
+  GstPad *sinkpad;
+  GstAggregator *aggregator;
+
+  g_return_val_if_fail (GST_IS_AGGREGATOR (element), NULL);
+
+  if (templ->direction != GST_PAD_SINK) {
+    g_warning ("gstaggregator: request new pad that is not a sink pad\n");
+    return NULL;
+  }
+
+  aggregator = GST_AGGREGATOR (element);
+
+  name = g_strdup_printf ("sink%d", aggregator->numsinkpads);
+
+  sinkpad = gst_pad_new_from_template (templ, name);
+  g_free (name);
+
+  if (!AGGREGATOR_IS_LOOP_BASED (aggregator)) {
+    gst_pad_set_chain_function (sinkpad, gst_aggregator_chain);
+  }
+  gst_pad_set_getcaps_function (sinkpad, gst_pad_proxy_getcaps);
+  gst_element_add_pad (GST_ELEMENT (aggregator), sinkpad);
+
+  aggregator->sinkpads = g_list_prepend (aggregator->sinkpads, sinkpad);
+  aggregator->numsinkpads++;
+
+  return sinkpad;
+}
+
+static void
+gst_aggregator_update_functions (GstAggregator * aggregator)
+{
+  GList *pads;
+
+  if (AGGREGATOR_IS_LOOP_BASED (aggregator)) {
+    gst_element_set_loop_function (GST_ELEMENT (aggregator),
+        GST_DEBUG_FUNCPTR (gst_aggregator_loop));
+  } else {
+    gst_element_set_loop_function (GST_ELEMENT (aggregator), NULL);
+  }
+
+  pads = aggregator->sinkpads;
+  while (pads) {
+    GstPad *pad = GST_PAD (pads->data);
+
+    if (AGGREGATOR_IS_LOOP_BASED (aggregator)) {
+      gst_pad_set_get_function (pad, NULL);
+    } else {
+      gst_element_set_loop_function (GST_ELEMENT (aggregator), NULL);
+    }
+    pads = g_list_next (pads);
+  }
+}
+
+static void
+gst_aggregator_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstAggregator *aggregator;
+
+  /* it's not null if we got it, but it might not be ours */
+  g_return_if_fail (GST_IS_AGGREGATOR (object));
+
+  aggregator = GST_AGGREGATOR (object);
+
+  switch (prop_id) {
+    case ARG_SILENT:
+      aggregator->silent = g_value_get_boolean (value);
+      break;
+    case ARG_SCHED:
+      aggregator->sched = g_value_get_enum (value);
+      gst_aggregator_update_functions (aggregator);
+      break;
+    default:
+      break;
+  }
+}
+
+static void
+gst_aggregator_get_property (GObject * object, guint prop_id, GValue * value,
+    GParamSpec * pspec)
+{
+  GstAggregator *aggregator;
+
+  /* it's not null if we got it, but it might not be ours */
+  g_return_if_fail (GST_IS_AGGREGATOR (object));
+
+  aggregator = GST_AGGREGATOR (object);
+
+  switch (prop_id) {
+    case ARG_NUM_PADS:
+      g_value_set_int (value, aggregator->numsinkpads);
+      break;
+    case ARG_SILENT:
+      g_value_set_boolean (value, aggregator->silent);
+      break;
+    case ARG_SCHED:
+      g_value_set_enum (value, aggregator->sched);
+      break;
+    case ARG_LAST_MESSAGE:
+      g_value_set_string (value, aggregator->last_message);
+      break;
+    default:
+      break;
+  }
+}
+
+static void
+gst_aggregator_push (GstAggregator * aggregator, GstPad * pad, GstBuffer * buf,
+    guchar * debug)
+{
+  if (!aggregator->silent) {
+    g_free (aggregator->last_message);
+
+    aggregator->last_message =
+        g_strdup_printf ("%10.10s ******* (%s:%s)a (%d bytes, %"
+        G_GUINT64_FORMAT ")", debug, GST_DEBUG_PAD_NAME (pad),
+        GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
+
+    g_object_notify (G_OBJECT (aggregator), "last_message");
+  }
+
+  gst_pad_push (aggregator->srcpad, GST_DATA (buf));
+}
+
+static void
+gst_aggregator_loop (GstElement * element)
+{
+  GstAggregator *aggregator;
+  GstBuffer *buf;
+  guchar *debug;
+
+  aggregator = GST_AGGREGATOR (element);
+
+  if (aggregator->sched == AGGREGATOR_LOOP) {
+    GList *pads = aggregator->sinkpads;
+
+    /* we'll loop over all pads and try to pull from all
+     * active ones */
+    while (pads) {
+      GstPad *pad = GST_PAD (pads->data);
+
+      pads = g_list_next (pads);
+
+      /* we need to check is the pad is usable. IS_USABLE will check
+       * if the pad is linked, if it is enabled (the element is
+       * playing and the app didn't gst_pad_set_enabled (pad, FALSE))
+       * and that the peer pad is also enabled.
+       */
+      if (GST_PAD_IS_USABLE (pad)) {
+        buf = GST_BUFFER (gst_pad_pull (pad));
+        debug = "loop";
+
+        /* then push it forward */
+        gst_aggregator_push (aggregator, pad, buf, debug);
+      }
+    }
+  } else {
+    if (aggregator->sched == AGGREGATOR_LOOP_SELECT) {
+      GstPad *pad;
+
+      debug = "loop_select";
+
+      buf = GST_BUFFER (gst_pad_collectv (&pad, aggregator->sinkpads));
+
+      gst_aggregator_push (aggregator, pad, buf, debug);
+    } else {
+      g_assert_not_reached ();
+    }
+  }
+}
+
+/**
+ * gst_aggregator_chain:
+ * @pad: the pad to follow
+ * @buf: the buffer to pass
+ *
+ * Chain a buffer on a pad.
+ */
+static void
+gst_aggregator_chain (GstPad * pad, GstData * _data)
+{
+  GstBuffer *buf = GST_BUFFER (_data);
+  GstAggregator *aggregator;
+
+  g_return_if_fail (pad != NULL);
+  g_return_if_fail (GST_IS_PAD (pad));
+  g_return_if_fail (buf != NULL);
+
+  aggregator = GST_AGGREGATOR (gst_pad_get_parent (pad));
+/*  gst_trace_add_entry (NULL, 0, buf, "aggregator buffer");*/
+
+  gst_aggregator_push (aggregator, pad, buf, "chain");
+}
diff --git a/gst/oldcore/gstaggregator.h b/gst/oldcore/gstaggregator.h
new file mode 100644 (file)
index 0000000..24af881
--- /dev/null
@@ -0,0 +1,74 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ *                    2000 Wim Taymans <wtay@chello.be>
+ *
+ * gstaggregator.h: Header for GstAggregator element
+ *
+ * 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.
+ */
+
+
+#ifndef __GST_AGGREGATOR_H__
+#define __GST_AGGREGATOR_H__
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+
+typedef enum {
+  AGGREGATOR_LOOP              = 1,
+  AGGREGATOR_LOOP_SELECT,
+  AGGREGATOR_CHAIN
+} GstAggregatorSchedType;
+
+#define GST_TYPE_AGGREGATOR \
+  (gst_aggregator_get_type())
+#define GST_AGGREGATOR(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AGGREGATOR,GstAggregator))
+#define GST_AGGREGATOR_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AGGREGATOR,GstAggregatorClass))
+#define GST_IS_AGGREGATOR(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AGGREGATOR))
+#define GST_IS_AGGREGATOR_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AGGREGATOR))
+
+typedef struct _GstAggregator          GstAggregator;
+typedef struct _GstAggregatorClass     GstAggregatorClass;
+
+struct _GstAggregator {
+  GstElement element;
+
+  GstPad *srcpad;
+
+  gboolean silent;
+  GstAggregatorSchedType sched;
+
+  gint numsinkpads;
+  GList *sinkpads;
+
+  gchar *last_message;
+};
+
+struct _GstAggregatorClass {
+  GstElementClass parent_class;
+};
+
+GType  gst_aggregator_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_AGGREGATOR_H__ */
diff --git a/gst/oldcore/gstelements.c b/gst/oldcore/gstelements.c
new file mode 100644 (file)
index 0000000..7c7d5a8
--- /dev/null
@@ -0,0 +1,82 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ *                    2000 Wim Taymans <wtay@chello.be>
+ *
+ * gstelements.c:
+ *
+ * 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.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include <gst/gst.h>
+
+#include "gstaggregator.h"
+#include "gstfdsink.h"
+#include "gstfdsrc.h"
+#include "gstmd5sink.h"
+#include "gstmultifilesrc.h"
+#include "gstpipefilter.h"
+#include "gstshaper.h"
+#include "gststatistics.h"
+
+struct _elements_entry
+{
+  gchar *name;
+  guint rank;
+    GType (*type) (void);
+};
+
+
+extern GType gst_capsfilter_get_type (void);
+extern GType gst_filesrc_get_type (void);
+extern GstElementDetails gst_filesrc_details;
+
+static struct _elements_entry _elements[] = {
+  {"aggregator", GST_RANK_NONE, gst_aggregator_get_type},
+  {"fdsink", GST_RANK_NONE, gst_fdsink_get_type},
+  {"fdsrc", GST_RANK_NONE, gst_fdsrc_get_type},
+  {"md5sink", GST_RANK_NONE, gst_md5sink_get_type},
+  {"multifilesrc", GST_RANK_NONE, gst_multifilesrc_get_type},
+  {"pipefilter", GST_RANK_NONE, gst_pipefilter_get_type},
+  {"shaper", GST_RANK_NONE, gst_shaper_get_type},
+  {"statistics", GST_RANK_NONE, gst_statistics_get_type},
+  {NULL, 0},
+};
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+  struct _elements_entry *my_elements = _elements;
+
+  while ((*my_elements).name) {
+    if (!gst_element_register (plugin, (*my_elements).name, (*my_elements).rank,
+            ((*my_elements).type) ()))
+      return FALSE;
+    my_elements++;
+  }
+
+  return TRUE;
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+    GST_VERSION_MINOR,
+    "gstelements",
+    "standard GStreamer elements",
+    plugin_init, VERSION, GST_LICENSE, GST_PACKAGE, GST_ORIGIN)
diff --git a/gst/oldcore/gstfdsink.c b/gst/oldcore/gstfdsink.c
new file mode 100644 (file)
index 0000000..1fca02c
--- /dev/null
@@ -0,0 +1,172 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ *                    2000 Wim Taymans <wtay@chello.be>
+ *
+ * gstfdsink.c: 
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include "gstfdsink.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS_ANY);
+
+GST_DEBUG_CATEGORY_STATIC (gst_fdsink_debug);
+#define GST_CAT_DEFAULT gst_fdsink_debug
+
+GstElementDetails gst_fdsink_details =
+GST_ELEMENT_DETAILS ("Filedescriptor Sink",
+    "Sink/File",
+    "Write data to a file descriptor",
+    "Erik Walthinsen <omega@cse.ogi.edu>");
+
+
+/* FdSink signals and args */
+enum
+{
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+enum
+{
+  ARG_0,
+  ARG_FD
+};
+
+
+#define _do_init(bla) \
+    GST_DEBUG_CATEGORY_INIT (gst_fdsink_debug, "fdsink", 0, "fdsink element");
+
+GST_BOILERPLATE_FULL (GstFdSink, gst_fdsink, GstElement, GST_TYPE_ELEMENT,
+    _do_init);
+
+static void gst_fdsink_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_fdsink_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+
+static void gst_fdsink_chain (GstPad * pad, GstData * _data);
+
+
+static void
+gst_fdsink_base_init (gpointer g_class)
+{
+  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&sinktemplate));
+  gst_element_class_set_details (gstelement_class, &gst_fdsink_details);
+}
+static void
+gst_fdsink_class_init (GstFdSinkClass * klass)
+{
+  GObjectClass *gobject_class;
+
+  gobject_class = G_OBJECT_CLASS (klass);
+
+  gobject_class->set_property = gst_fdsink_set_property;
+  gobject_class->get_property = gst_fdsink_get_property;
+
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FD,
+      g_param_spec_int ("fd", "fd", "An open file descriptor to write to",
+          0, G_MAXINT, 1, G_PARAM_READWRITE));
+}
+
+static void
+gst_fdsink_init (GstFdSink * fdsink)
+{
+  fdsink->sinkpad =
+      gst_pad_new_from_template (gst_static_pad_template_get (&sinktemplate),
+      "sink");
+  gst_element_add_pad (GST_ELEMENT (fdsink), fdsink->sinkpad);
+  gst_pad_set_chain_function (fdsink->sinkpad, gst_fdsink_chain);
+
+  fdsink->fd = 1;
+}
+
+static void
+gst_fdsink_chain (GstPad * pad, GstData * _data)
+{
+  GstBuffer *buf = GST_BUFFER (_data);
+  GstFdSink *fdsink;
+
+  g_return_if_fail (pad != NULL);
+  g_return_if_fail (GST_IS_PAD (pad));
+  g_return_if_fail (buf != NULL);
+
+  fdsink = GST_FDSINK (gst_pad_get_parent (pad));
+
+  g_return_if_fail (fdsink->fd >= 0);
+
+  if (GST_BUFFER_DATA (buf)) {
+    GST_DEBUG ("writing %d bytes to file descriptor %d", GST_BUFFER_SIZE (buf),
+        fdsink->fd);
+    write (fdsink->fd, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
+  }
+
+  gst_buffer_unref (buf);
+}
+
+static void
+gst_fdsink_set_property (GObject * object, guint prop_id, const GValue * value,
+    GParamSpec * pspec)
+{
+  GstFdSink *fdsink;
+
+  /* it's not null if we got it, but it might not be ours */
+  g_return_if_fail (GST_IS_FDSINK (object));
+
+  fdsink = GST_FDSINK (object);
+
+  switch (prop_id) {
+    case ARG_FD:
+      fdsink->fd = g_value_get_int (value);
+      break;
+    default:
+      break;
+  }
+}
+
+static void
+gst_fdsink_get_property (GObject * object, guint prop_id, GValue * value,
+    GParamSpec * pspec)
+{
+  GstFdSink *fdsink;
+
+  /* it's not null if we got it, but it might not be ours */
+  g_return_if_fail (GST_IS_FDSINK (object));
+
+  fdsink = GST_FDSINK (object);
+
+  switch (prop_id) {
+    case ARG_FD:
+      g_value_set_int (value, fdsink->fd);
+      break;
+    default:
+      break;
+  }
+}
diff --git a/gst/oldcore/gstfdsink.h b/gst/oldcore/gstfdsink.h
new file mode 100644 (file)
index 0000000..838705a
--- /dev/null
@@ -0,0 +1,62 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ *                    2000 Wim Taymans <wtay@chello.be>
+ *
+ * gstfdsink.h: 
+ *
+ * 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.
+ */
+
+
+#ifndef __GST_FDSINK_H__
+#define __GST_FDSINK_H__
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+
+#define GST_TYPE_FDSINK \
+  (gst_fdsink_get_type())
+#define GST_FDSINK(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FDSINK,GstFdSink))
+#define GST_FDSINK_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FDSINK,GstFdSinkClass))
+#define GST_IS_FDSINK(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FDSINK))
+#define GST_IS_FDSINK_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FDSINK))
+
+typedef struct _GstFdSink GstFdSink;
+typedef struct _GstFdSinkClass GstFdSinkClass;
+
+struct _GstFdSink {
+  GstElement element;
+
+  GstPad *sinkpad;
+
+  int fd;
+};
+
+struct _GstFdSinkClass {
+  GstElementClass parent_class;
+};
+
+GType gst_fdsink_get_type(void);
+
+G_END_DECLS
+
+#endif /* __GST_FDSINK_H__ */
diff --git a/gst/oldcore/gstmd5sink.c b/gst/oldcore/gstmd5sink.c
new file mode 100644 (file)
index 0000000..4ebbb4c
--- /dev/null
@@ -0,0 +1,497 @@
+/* GStreamer
+ * Copyright (C) 2002 Erik Walthinsen <omega@cse.ogi.edu>
+ *               2002 Wim Taymans <wim.taymans@chello.be>
+ *
+ * gstmd5sink.c: A sink computing an md5 checksum from a stream
+ *
+ * The md5 code was taken from glibc-2.2.3/crypt/md5.c and slightly
+ * modified.
+ *
+ * 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 <string.h>
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include "gstmd5sink.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_md5sink_debug);
+#define GST_CAT_DEFAULT gst_md5sink_debug
+
+GstElementDetails gst_md5sink_details = GST_ELEMENT_DETAILS ("MD5 Sink",
+    "Sink",
+    "compute MD5 for incoming data",
+    "Benjamin Otte <in7y118@public.uni-hamburg.de>");
+
+/* MD5Sink signals and args */
+enum
+{
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+enum
+{
+  ARG_0,
+  ARG_MD5
+      /* FILL ME */
+};
+
+GstStaticPadTemplate md5_sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS_ANY);
+
+#define _do_init(bla) \
+    GST_DEBUG_CATEGORY_INIT (gst_md5sink_debug, "md5sink", 0, "md5sink element");
+
+GST_BOILERPLATE_FULL (GstMD5Sink, gst_md5sink, GstElement, GST_TYPE_ELEMENT,
+    _do_init);
+
+/* GObject stuff */
+/*static void                  gst_md5sink_set_property        (GObject *object, guint prop_id, 
+                                                        const GValue *value, GParamSpec *pspec);*/
+static void gst_md5sink_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+
+static void gst_md5sink_chain (GstPad * pad, GstData * _data);
+static GstElementStateReturn gst_md5sink_change_state (GstElement * element);
+
+
+/* MD5 stuff */
+static void md5_init_ctx (GstMD5Sink * ctx);
+static gpointer md5_read_ctx (GstMD5Sink * ctx, gpointer resbuf);
+static gpointer md5_finish_ctx (GstMD5Sink * ctx, gpointer resbuf);
+static void md5_process_bytes (const void *buffer, size_t len,
+    GstMD5Sink * ctx);
+static void md5_process_block (const void *buffer, size_t len,
+    GstMD5Sink * ctx);
+
+/* This array contains the bytes used to pad the buffer to the next
+   64-byte boundary.  (RFC 1321, 3.1: Step 1)  */
+static const guchar fillbuf[64] = { 0x80, 0 /* , 0, 0, ...  */  };
+
+/* MD5 functions */
+/* Initialize structure containing state of computation.
+   (RFC 1321, 3.3: Step 3)  */
+static void
+md5_init_ctx (GstMD5Sink * ctx)
+{
+  ctx->A = 0x67452301;
+  ctx->B = 0xefcdab89;
+  ctx->C = 0x98badcfe;
+  ctx->D = 0x10325476;
+
+  ctx->total[0] = ctx->total[1] = 0;
+  ctx->buflen = 0;
+}
+
+/* Process the remaining bytes in the internal buffer and the usual
+   prolog according to the standard and write the result to RESBUF.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+static gpointer
+md5_finish_ctx (GstMD5Sink * ctx, gpointer resbuf)
+{
+  /* Take yet unprocessed bytes into account.  */
+  guint32 bytes = ctx->buflen;
+  size_t pad;
+
+  /* Now count remaining bytes.  */
+  ctx->total[0] += bytes;
+  if (ctx->total[0] < bytes)
+    ++ctx->total[1];
+
+  pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
+  memcpy (&ctx->buffer[bytes], fillbuf, pad);
+
+  /* Put the 64-bit file length in *bits* at the end of the buffer.  */
+  *(guint32 *) & ctx->buffer[bytes + pad] = GUINT32_TO_LE (ctx->total[0] << 3);
+  *(guint32 *) & ctx->buffer[bytes + pad + 4] =
+      GUINT32_TO_LE ((ctx->total[1] << 3) | (ctx->total[0] >> 29));
+
+  /* Process last bytes.  */
+  md5_process_block (ctx->buffer, bytes + pad + 8, ctx);
+
+  return md5_read_ctx (ctx, resbuf);
+}
+
+/* Put result from CTX in first 16 bytes following RESBUF.  The result
+   must be in little endian byte order.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+static gpointer
+md5_read_ctx (GstMD5Sink * ctx, gpointer resbuf)
+{
+  ((guint32 *) resbuf)[0] = GUINT32_TO_LE (ctx->A);
+  ((guint32 *) resbuf)[1] = GUINT32_TO_LE (ctx->B);
+  ((guint32 *) resbuf)[2] = GUINT32_TO_LE (ctx->C);
+  ((guint32 *) resbuf)[3] = GUINT32_TO_LE (ctx->D);
+
+  return resbuf;
+}
+
+static void
+md5_process_bytes (const void *buffer, size_t len, GstMD5Sink * ctx)
+{
+  /*const void aligned_buffer = buffer; */
+
+  /* When we already have some bits in our internal buffer concatenate
+     both inputs first.  */
+  if (ctx->buflen != 0) {
+    size_t left_over = ctx->buflen;
+    size_t add = 128 - left_over > len ? len : 128 - left_over;
+
+    /* Only put full words in the buffer.  */
+    /* Forcing alignment here appears to be only an optimization.
+     * The glibc source uses __alignof__, which seems to be a
+     * gratuitous usage of a GCC extension, when sizeof() will
+     * work fine.  (And don't question the sanity of using
+     * sizeof(guint32) instead of 4. */
+    /* add -= add % __alignof__ (guint32); */
+    add -= add % sizeof (guint32);
+
+    memcpy (&ctx->buffer[left_over], buffer, add);
+    ctx->buflen += add;
+
+    if (ctx->buflen > 64) {
+      md5_process_block (ctx->buffer, ctx->buflen & ~63, ctx);
+
+      ctx->buflen &= 63;
+      /* The regions in the following copy operation cannot overlap.  */
+      memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63], ctx->buflen);
+    }
+
+    buffer = (const char *) buffer + add;
+    len -= add;
+  }
+
+  /* Process available complete blocks.  */
+  if (len > 64) {
+    md5_process_block (buffer, len & ~63, ctx);
+    buffer = (const char *) buffer + (len & ~63);
+    len &= 63;
+  }
+
+  /* Move remaining bytes in internal buffer.  */
+  if (len > 0) {
+    size_t left_over = ctx->buflen;
+
+    memcpy (&ctx->buffer[left_over], buffer, len);
+    left_over += len;
+    if (left_over >= 64) {
+      md5_process_block (ctx->buffer, 64, ctx);
+      left_over -= 64;
+      memcpy (ctx->buffer, &ctx->buffer[64], left_over);
+    }
+    ctx->buflen = left_over;
+  }
+}
+
+
+/* These are the four functions used in the four steps of the MD5 algorithm
+   and defined in the RFC 1321.  The first function is a little bit optimized
+   (as found in Colin Plumbs public domain implementation).  */
+/* #define FF(b, c, d) ((b & c) | (~b & d)) */
+#define FF(b, c, d) (d ^ (b & (c ^ d)))
+#define FG(b, c, d) FF (d, b, c)
+#define FH(b, c, d) (b ^ c ^ d)
+#define FI(b, c, d) (c ^ (b | ~d))
+
+/* Process LEN bytes of BUFFER, accumulating context into CTX.
+   It is assumed that LEN % 64 == 0.  */
+static void
+md5_process_block (const void *buffer, size_t len, GstMD5Sink * ctx)
+{
+  guint32 correct_words[16];
+  const guint32 *words = buffer;
+  size_t nwords = len / sizeof (guint32);
+  const guint32 *endp = words + nwords;
+  guint32 A = ctx->A;
+  guint32 B = ctx->B;
+  guint32 C = ctx->C;
+  guint32 D = ctx->D;
+
+  /* First increment the byte count.  RFC 1321 specifies the possible
+     length of the file up to 2^64 bits.  Here we only compute the
+     number of bytes.  Do a double word increment.  */
+  ctx->total[0] += len;
+  if (ctx->total[0] < len)
+    ++ctx->total[1];
+
+  /* Process all bytes in the buffer with 64 bytes in each round of
+     the loop.  */
+  while (words < endp) {
+    guint32 *cwp = correct_words;
+    guint32 A_save = A;
+    guint32 B_save = B;
+    guint32 C_save = C;
+    guint32 D_save = D;
+
+    /* First round: using the given function, the context and a constant
+       the next context is computed.  Because the algorithms processing
+       unit is a 32-bit word and it is determined to work on words in
+       little endian byte order we perhaps have to change the byte order
+       before the computation.  To reduce the work for the next steps
+       we store the swapped words in the array CORRECT_WORDS.  */
+
+#define OP(a, b, c, d, s, T)                                           \
+      do                                                               \
+        {                                                              \
+         a += FF (b, c, d) + (*cwp++ = GUINT32_TO_LE (*words)) + T;            \
+         ++words;                                                      \
+         CYCLIC (a, s);                                                \
+         a += b;                                                       \
+        }                                                              \
+      while (0)
+
+    /* It is unfortunate that C does not provide an operator for
+       cyclic rotation.  Hope the C compiler is smart enough.  */
+#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
+
+    /* Before we start, one word to the strange constants.
+       They are defined in RFC 1321 as
+
+       T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
+     */
+
+    /* Round 1.  */
+    OP (A, B, C, D, 7, 0xd76aa478);
+    OP (D, A, B, C, 12, 0xe8c7b756);
+    OP (C, D, A, B, 17, 0x242070db);
+    OP (B, C, D, A, 22, 0xc1bdceee);
+    OP (A, B, C, D, 7, 0xf57c0faf);
+    OP (D, A, B, C, 12, 0x4787c62a);
+    OP (C, D, A, B, 17, 0xa8304613);
+    OP (B, C, D, A, 22, 0xfd469501);
+    OP (A, B, C, D, 7, 0x698098d8);
+    OP (D, A, B, C, 12, 0x8b44f7af);
+    OP (C, D, A, B, 17, 0xffff5bb1);
+    OP (B, C, D, A, 22, 0x895cd7be);
+    OP (A, B, C, D, 7, 0x6b901122);
+    OP (D, A, B, C, 12, 0xfd987193);
+    OP (C, D, A, B, 17, 0xa679438e);
+    OP (B, C, D, A, 22, 0x49b40821);
+
+    /* For the second to fourth round we have the possibly swapped words
+       in CORRECT_WORDS.  Redefine the macro to take an additional first
+       argument specifying the function to use.  */
+#undef OP
+#define OP(f, a, b, c, d, k, s, T)                                     \
+      do                                                               \
+       {                                                               \
+         a += f (b, c, d) + correct_words[k] + T;                      \
+         CYCLIC (a, s);                                                \
+         a += b;                                                       \
+       }                                                               \
+      while (0)
+
+    /* Round 2.  */
+    OP (FG, A, B, C, D, 1, 5, 0xf61e2562);
+    OP (FG, D, A, B, C, 6, 9, 0xc040b340);
+    OP (FG, C, D, A, B, 11, 14, 0x265e5a51);
+    OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa);
+    OP (FG, A, B, C, D, 5, 5, 0xd62f105d);
+    OP (FG, D, A, B, C, 10, 9, 0x02441453);
+    OP (FG, C, D, A, B, 15, 14, 0xd8a1e681);
+    OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8);
+    OP (FG, A, B, C, D, 9, 5, 0x21e1cde6);
+    OP (FG, D, A, B, C, 14, 9, 0xc33707d6);
+    OP (FG, C, D, A, B, 3, 14, 0xf4d50d87);
+    OP (FG, B, C, D, A, 8, 20, 0x455a14ed);
+    OP (FG, A, B, C, D, 13, 5, 0xa9e3e905);
+    OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8);
+    OP (FG, C, D, A, B, 7, 14, 0x676f02d9);
+    OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
+
+    /* Round 3.  */
+    OP (FH, A, B, C, D, 5, 4, 0xfffa3942);
+    OP (FH, D, A, B, C, 8, 11, 0x8771f681);
+    OP (FH, C, D, A, B, 11, 16, 0x6d9d6122);
+    OP (FH, B, C, D, A, 14, 23, 0xfde5380c);
+    OP (FH, A, B, C, D, 1, 4, 0xa4beea44);
+    OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9);
+    OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60);
+    OP (FH, B, C, D, A, 10, 23, 0xbebfbc70);
+    OP (FH, A, B, C, D, 13, 4, 0x289b7ec6);
+    OP (FH, D, A, B, C, 0, 11, 0xeaa127fa);
+    OP (FH, C, D, A, B, 3, 16, 0xd4ef3085);
+    OP (FH, B, C, D, A, 6, 23, 0x04881d05);
+    OP (FH, A, B, C, D, 9, 4, 0xd9d4d039);
+    OP (FH, D, A, B, C, 12, 11, 0xe6db99e5);
+    OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8);
+    OP (FH, B, C, D, A, 2, 23, 0xc4ac5665);
+
+    /* Round 4.  */
+    OP (FI, A, B, C, D, 0, 6, 0xf4292244);
+    OP (FI, D, A, B, C, 7, 10, 0x432aff97);
+    OP (FI, C, D, A, B, 14, 15, 0xab9423a7);
+    OP (FI, B, C, D, A, 5, 21, 0xfc93a039);
+    OP (FI, A, B, C, D, 12, 6, 0x655b59c3);
+    OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92);
+    OP (FI, C, D, A, B, 10, 15, 0xffeff47d);
+    OP (FI, B, C, D, A, 1, 21, 0x85845dd1);
+    OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f);
+    OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
+    OP (FI, C, D, A, B, 6, 15, 0xa3014314);
+    OP (FI, B, C, D, A, 13, 21, 0x4e0811a1);
+    OP (FI, A, B, C, D, 4, 6, 0xf7537e82);
+    OP (FI, D, A, B, C, 11, 10, 0xbd3af235);
+    OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb);
+    OP (FI, B, C, D, A, 9, 21, 0xeb86d391);
+
+    /* Add the starting values of the context.  */
+    A += A_save;
+    B += B_save;
+    C += C_save;
+    D += D_save;
+  }
+
+  /* Put checksum in context given as argument.  */
+  ctx->A = A;
+  ctx->B = B;
+  ctx->C = C;
+  ctx->D = D;
+}
+
+static void
+gst_md5sink_base_init (gpointer g_class)
+{
+  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_set_details (gstelement_class, &gst_md5sink_details);
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&md5_sink_template));
+}
+
+static void
+gst_md5sink_class_init (GstMD5SinkClass * klass)
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+
+  gobject_class = (GObjectClass *) klass;
+  gstelement_class = (GstElementClass *) klass;
+
+  gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_md5sink_get_property);
+
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MD5,
+      g_param_spec_string ("md5", "md5", "current value of the md5 sum",
+          "", G_PARAM_READABLE));
+
+  gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_md5sink_change_state);
+}
+
+static void
+gst_md5sink_init (GstMD5Sink * md5sink)
+{
+  GstPad *pad;
+
+  pad =
+      gst_pad_new_from_template (gst_static_pad_template_get
+      (&md5_sink_template), "sink");
+  gst_element_add_pad (GST_ELEMENT (md5sink), pad);
+  gst_pad_set_chain_function (pad, GST_DEBUG_FUNCPTR (gst_md5sink_chain));
+
+  md5_init_ctx (md5sink);
+}
+
+static GstElementStateReturn
+gst_md5sink_change_state (GstElement * element)
+{
+  GstMD5Sink *sink;
+
+  /* element check */
+  sink = GST_MD5SINK (element);
+
+  g_return_val_if_fail (GST_IS_MD5SINK (sink), GST_STATE_FAILURE);
+
+  switch (GST_STATE_TRANSITION (element)) {
+    case GST_STATE_READY_TO_PAUSED:
+      md5_init_ctx (sink);
+      g_object_notify (G_OBJECT (element), "md5");
+      break;
+    case GST_STATE_PAUSED_TO_READY:
+      md5_finish_ctx (sink, sink->md5);
+      g_object_notify (G_OBJECT (element), "md5");
+      break;
+    default:
+      break;
+  }
+
+  if ((GST_ELEMENT_CLASS (parent_class)->change_state))
+    return GST_ELEMENT_CLASS (parent_class)->change_state (element);
+
+  return GST_STATE_SUCCESS;
+}
+
+static void
+gst_md5sink_get_property (GObject * object, guint prop_id, GValue * value,
+    GParamSpec * pspec)
+{
+  GstMD5Sink *sink;
+
+  /* it's not null if we got it, but it might not be ours */
+  g_return_if_fail (GST_IS_MD5SINK (object));
+
+  sink = GST_MD5SINK (object);
+
+  switch (prop_id) {
+    case ARG_MD5:
+    {
+      /* you could actually get a value for the current md5. 
+       * This is currently disabled.
+       * md5_read_ctx (sink, sink->md5); */
+      /* md5 is a guchar[16] */
+      int i;
+      guchar *md5string = g_malloc0 (33);
+
+      for (i = 0; i < 16; ++i)
+        sprintf (md5string + i * 2, "%02x", sink->md5[i]);
+      g_value_set_string (value, md5string);
+      g_free (md5string);
+    }
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_md5sink_chain (GstPad * pad, GstData * _data)
+{
+  GstBuffer *buf = GST_BUFFER (_data);
+  GstMD5Sink *md5sink;
+
+  g_return_if_fail (pad != NULL);
+  g_return_if_fail (GST_IS_PAD (pad));
+  g_return_if_fail (buf != NULL);
+
+  md5sink = GST_MD5SINK (gst_pad_get_parent (pad));
+
+  if (GST_IS_BUFFER (buf)) {
+    md5_process_bytes (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf), md5sink);
+  }
+
+  gst_buffer_unref (buf);
+}
diff --git a/gst/oldcore/gstmd5sink.h b/gst/oldcore/gstmd5sink.h
new file mode 100644 (file)
index 0000000..d2b8109
--- /dev/null
@@ -0,0 +1,74 @@
+/* GStreamer
+ * Copyright (C) 2002 Erik Walthinsen <omega@cse.ogi.edu>
+ *               2002 Wim Taymans <wtay@chello.be>
+ *
+ * gstmd5sink.h: 
+ *
+ * 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.
+ */
+
+
+#ifndef __GST_MD5SINK_H__
+#define __GST_MD5SINK_H__
+
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+
+#define GST_TYPE_MD5SINK \
+  (gst_md5sink_get_type())
+#define GST_MD5SINK(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MD5SINK,GstMD5Sink))
+#define GST_MD5SINK_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MD5SINK,GstMD5SinkClass))
+#define GST_IS_MD5SINK(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MD5SINK))
+#define GST_IS_MD5SINK_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_MD5SINK))
+
+typedef struct _GstMD5Sink GstMD5Sink;
+typedef struct _GstMD5SinkClass GstMD5SinkClass;
+
+struct _GstMD5Sink {
+  GstElement element;
+
+  /* md5 information */
+  guint32 A;
+  guint32 B;
+  guint32 C;
+  guint32 D;
+
+  guint32 total[2];
+  guint32 buflen;
+  gchar buffer[128];
+  
+  /* latest md5 */
+  guchar md5[16];
+  
+};
+
+struct _GstMD5SinkClass {
+  GstElementClass parent_class;
+
+};
+
+GType                          gst_md5sink_get_type            (void);
+
+G_END_DECLS
+
+#endif /* __GST_MD5SINK_H__ */
diff --git a/gst/oldcore/gstmultifilesrc.c b/gst/oldcore/gstmultifilesrc.c
new file mode 100644 (file)
index 0000000..ea95173
--- /dev/null
@@ -0,0 +1,363 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ *                    2000 Wim Taymans <wtay@chello.be>
+ *                    2001 Dominic Ludlam <dom@recoil.org>
+ *
+ * gstmultifilesrc.c:
+ *
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <string.h>
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include "../gst-i18n-lib.h"
+
+#include "gstmultifilesrc.h"
+
+static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS_ANY);
+
+GST_DEBUG_CATEGORY_STATIC (gst_multifilesrc_debug);
+#define GST_CAT_DEFAULT gst_multifilesrc_debug
+
+GstElementDetails gst_multifilesrc_details =
+GST_ELEMENT_DETAILS ("Multi File Source",
+    "Source/File",
+    "Read from multiple files in order",
+    "Dominic Ludlam <dom@openfx.org>");
+
+/* FileSrc signals and args */
+enum
+{
+  NEW_FILE,
+  LAST_SIGNAL
+};
+
+enum
+{
+  ARG_0,
+  ARG_LOCATIONS,
+  ARG_HAVENEWMEDIA
+};
+
+#define _do_init(bla) \
+    GST_DEBUG_CATEGORY_INIT (gst_multifilesrc_debug, "multifilesrc", 0, "multifilesrc element");
+
+GST_BOILERPLATE_FULL (GstMultiFileSrc, gst_multifilesrc, GstElement,
+    GST_TYPE_ELEMENT, _do_init);
+
+static void gst_multifilesrc_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_multifilesrc_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+
+static GstData *gst_multifilesrc_get (GstPad * pad);
+
+/*static GstBuffer *   gst_multifilesrc_get_region     (GstPad *pad,GstRegionType type,guint64 offset,guint64 len);*/
+
+static GstElementStateReturn gst_multifilesrc_change_state (GstElement *
+    element);
+
+static gboolean gst_multifilesrc_open_file (GstMultiFileSrc * src,
+    GstPad * srcpad);
+static void gst_multifilesrc_close_file (GstMultiFileSrc * src);
+
+static guint gst_multifilesrc_signals[LAST_SIGNAL] = { 0 };
+
+static void
+gst_multifilesrc_base_init (gpointer g_class)
+{
+  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&srctemplate));
+  gst_element_class_set_details (gstelement_class, &gst_multifilesrc_details);
+}
+static void
+gst_multifilesrc_class_init (GstMultiFileSrcClass * klass)
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+
+  gobject_class = (GObjectClass *) klass;
+  gstelement_class = (GstElementClass *) klass;
+
+  gobject_class->set_property = gst_multifilesrc_set_property;
+  gobject_class->get_property = gst_multifilesrc_get_property;
+
+  gst_multifilesrc_signals[NEW_FILE] =
+      g_signal_new ("new-file", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
+      G_STRUCT_OFFSET (GstMultiFileSrcClass, new_file), NULL, NULL,
+      g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING);
+
+
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LOCATIONS, g_param_spec_pointer ("locations", "locations", "locations", G_PARAM_READWRITE));     /* CHECKME */
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_HAVENEWMEDIA,
+      g_param_spec_boolean ("newmedia", "newmedia",
+          "generate new media events?", FALSE, G_PARAM_READWRITE));
+
+  gstelement_class->change_state = gst_multifilesrc_change_state;
+}
+
+static void
+gst_multifilesrc_init (GstMultiFileSrc * multifilesrc)
+{
+/*  GST_FLAG_SET (filesrc, GST_SRC_); */
+
+  multifilesrc->srcpad =
+      gst_pad_new_from_template (gst_static_pad_template_get (&srctemplate),
+      "src");
+  gst_pad_set_get_function (multifilesrc->srcpad, gst_multifilesrc_get);
+/*  gst_pad_set_getregion_function (multifilesrc->srcpad,gst_multifilesrc_get_region); */
+  gst_element_add_pad (GST_ELEMENT (multifilesrc), multifilesrc->srcpad);
+
+  multifilesrc->listptr = NULL;
+  multifilesrc->currentfilename = NULL;
+  multifilesrc->fd = 0;
+  multifilesrc->size = 0;
+  multifilesrc->map = NULL;
+  multifilesrc->new_seek = FALSE;
+  multifilesrc->have_newmedia_events = FALSE;
+}
+
+static void
+gst_multifilesrc_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstMultiFileSrc *src;
+
+  /* it's not null if we got it, but it might not be ours */
+  g_return_if_fail (GST_IS_MULTIFILESRC (object));
+
+  src = GST_MULTIFILESRC (object);
+
+  switch (prop_id) {
+    case ARG_LOCATIONS:
+      /* the element must be stopped in order to do this */
+      g_return_if_fail (GST_STATE (src) < GST_STATE_PLAYING);
+
+      /* clear the filename if we get a NULL */
+      if (g_value_get_pointer (value) == NULL) {
+        gst_element_set_state (GST_ELEMENT (object), GST_STATE_NULL);
+        src->listptr = NULL;
+        /* otherwise set the new filenames */
+      } else {
+        src->listptr = g_value_get_pointer (value);
+      }
+      break;
+    case ARG_HAVENEWMEDIA:
+      src->have_newmedia_events = g_value_get_boolean (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_multifilesrc_get_property (GObject * object, guint prop_id, GValue * value,
+    GParamSpec * pspec)
+{
+  GstMultiFileSrc *src;
+
+  /* it's not null if we got it, but it might not be ours */
+  g_return_if_fail (GST_IS_MULTIFILESRC (object));
+
+  src = GST_MULTIFILESRC (object);
+
+  switch (prop_id) {
+    case ARG_LOCATIONS:
+      g_value_set_pointer (value, src->listptr);
+      break;
+    case ARG_HAVENEWMEDIA:
+      g_value_set_boolean (value, src->have_newmedia_events);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+/**
+ * gst_filesrc_get:
+ * @pad: #GstPad to push a buffer from
+ *
+ * Push a new buffer from the filesrc at the current offset.
+ */
+static GstData *
+gst_multifilesrc_get (GstPad * pad)
+{
+  GstMultiFileSrc *src;
+  GstBuffer *buf;
+  GstEvent *newmedia;
+  GSList *list;
+
+
+  g_return_val_if_fail (pad != NULL, NULL);
+  src = GST_MULTIFILESRC (gst_pad_get_parent (pad));
+
+  GST_DEBUG ("curfileindex = %d newmedia flag = %s", src->curfileindex,
+      GST_FLAG_IS_SET (src, GST_MULTIFILESRC_NEWFILE) ? "true" : "false");
+
+  switch (GST_FLAG_IS_SET (src, GST_MULTIFILESRC_NEWFILE)) {
+    case FALSE:
+      if (GST_FLAG_IS_SET (src, GST_MULTIFILESRC_OPEN))
+        gst_multifilesrc_close_file (src);
+
+      if (!src->listptr) {
+        GST_DEBUG ("sending EOS event");
+        gst_element_set_eos (GST_ELEMENT (src));
+        return GST_DATA (gst_event_new (GST_EVENT_EOS));
+      }
+
+      list = src->listptr;
+      src->currentfilename = (gchar *) list->data;
+      src->listptr = src->listptr->next;
+
+      if (!gst_multifilesrc_open_file (src, pad))
+        return NULL;
+      src->curfileindex++;
+      /* emitted after the open, as the user may free the list and string from here */
+      g_signal_emit (G_OBJECT (src), gst_multifilesrc_signals[NEW_FILE], 0,
+          list);
+      if (src->have_newmedia_events) {
+        newmedia =
+            gst_event_new_discontinuous (TRUE, GST_FORMAT_TIME, (gint64) 0,
+            GST_FORMAT_UNDEFINED);
+        GST_FLAG_SET (src, GST_MULTIFILESRC_NEWFILE);
+
+        GST_DEBUG ("sending new media event");
+        return GST_DATA (newmedia);
+      }
+    default:
+      if (GST_FLAG_IS_SET (src, GST_MULTIFILESRC_NEWFILE))
+        GST_FLAG_UNSET (src, GST_MULTIFILESRC_NEWFILE);
+      /* create the buffer */
+      /* FIXME: should eventually use a bufferpool for this */
+      buf = gst_buffer_new ();
+
+      g_return_val_if_fail (buf != NULL, NULL);
+
+      /* simply set the buffer to point to the correct region of the file */
+      GST_BUFFER_DATA (buf) = src->map;
+      GST_BUFFER_SIZE (buf) = src->size;
+      GST_BUFFER_OFFSET (buf) = 0;
+      GST_BUFFER_FLAG_SET (buf, GST_BUFFER_DONTFREE);
+
+      if (src->new_seek) {
+        /* fixme, do something here */
+        src->new_seek = FALSE;
+      }
+
+      /* we're done, return the buffer */
+      GST_DEBUG ("sending buffer");
+      return GST_DATA (buf);
+  }
+
+  /* should not reach here */
+  g_assert_not_reached ();
+  return NULL;
+}
+
+/* open the file and mmap it, necessary to go to READY state */
+static gboolean
+gst_multifilesrc_open_file (GstMultiFileSrc * src, GstPad * srcpad)
+{
+  g_return_val_if_fail (!GST_FLAG_IS_SET (src, GST_MULTIFILESRC_OPEN), FALSE);
+
+  if (src->currentfilename == NULL || src->currentfilename[0] == '\0') {
+    GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND,
+        (_("No file name specified for reading.")), (NULL));
+    return FALSE;
+  }
+
+  /* open the file. FIXME: do we need to use O_LARGEFILE here? */
+  src->fd = open ((const char *) src->currentfilename, O_RDONLY);
+  if (src->fd < 0) {
+    GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
+        (_("Could not open file \"%s\" for reading."), src->currentfilename),
+        GST_ERROR_SYSTEM);
+    return FALSE;
+
+  } else {
+    /* find the file length */
+    src->size = lseek (src->fd, 0, SEEK_END);
+    lseek (src->fd, 0, SEEK_SET);
+    /* map the file into memory. 
+     * FIXME: don't map the whole file at once, there might
+     *        be restrictions set. Get max size via getrlimit
+     *        or re-try with smaller size if mmap fails with ENOMEM? */
+    src->map = mmap (NULL, src->size, PROT_READ, MAP_SHARED, src->fd, 0);
+    madvise (src->map, src->size, MADV_SEQUENTIAL);
+    /* collapse state if that failed */
+    if (src->map == NULL) {
+      close (src->fd);
+      GST_ELEMENT_ERROR (src, RESOURCE, TOO_LAZY, (NULL),
+          ("mmap call failed."));
+      return FALSE;
+    }
+    GST_FLAG_SET (src, GST_MULTIFILESRC_OPEN);
+    src->new_seek = TRUE;
+  }
+  return TRUE;
+}
+
+/* unmap and close the file */
+static void
+gst_multifilesrc_close_file (GstMultiFileSrc * src)
+{
+  g_return_if_fail (GST_FLAG_IS_SET (src, GST_MULTIFILESRC_OPEN));
+
+  /* unmap the file from memory and close the file */
+  munmap (src->map, src->size);
+  close (src->fd);
+
+  /* zero out a lot of our state */
+  src->fd = 0;
+  src->size = 0;
+  src->map = NULL;
+  src->new_seek = FALSE;
+
+  GST_FLAG_UNSET (src, GST_MULTIFILESRC_OPEN);
+}
+
+static GstElementStateReturn
+gst_multifilesrc_change_state (GstElement * element)
+{
+  g_return_val_if_fail (GST_IS_MULTIFILESRC (element), GST_STATE_FAILURE);
+
+  if (GST_STATE_PENDING (element) == GST_STATE_NULL) {
+    if (GST_FLAG_IS_SET (element, GST_MULTIFILESRC_OPEN))
+      gst_multifilesrc_close_file (GST_MULTIFILESRC (element));
+  }
+
+  if (GST_ELEMENT_CLASS (parent_class)->change_state)
+    return GST_ELEMENT_CLASS (parent_class)->change_state (element);
+
+  return GST_STATE_SUCCESS;
+}
diff --git a/gst/oldcore/gstmultifilesrc.h b/gst/oldcore/gstmultifilesrc.h
new file mode 100644 (file)
index 0000000..077d69e
--- /dev/null
@@ -0,0 +1,85 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ *                    2000 Wim Taymans <wtay@chello.be>
+ *                    2001 Dominic Ludlam <dom@recoil.org>
+ *
+ * gstmultifilesrc.h: 
+ *
+ * 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.
+ */
+
+#ifndef __GST_MULTIFILESRC_H__
+#define __GST_MULTIFILESRC_H__
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+
+#define GST_TYPE_MULTIFILESRC \
+  (gst_multifilesrc_get_type())
+#define GST_MULTIFILESRC(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MULTIFILESRC,GstMultiFileSrc))
+#define GST_MULTIFILESRC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MULTIFILESRC,GstMultiFileSrcClass))
+#define GST_IS_MULTIFILESRC(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MULTIFILESRC))
+#define GST_IS_MULTIFILESRC_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_MULTIFILESRC))
+
+typedef enum {
+  GST_MULTIFILESRC_OPEN                = GST_ELEMENT_FLAG_LAST,
+  GST_MULTIFILESRC_NEWFILE      = GST_ELEMENT_FLAG_LAST + 2,
+
+  GST_MULTIFILESRC_FLAG_LAST   = GST_ELEMENT_FLAG_LAST + 4
+} GstMultiFileSrcFlags;
+
+typedef struct _GstMultiFileSrc GstMultiFileSrc;
+typedef struct _GstMultiFileSrcClass GstMultiFileSrcClass;
+
+struct _GstMultiFileSrc {
+  GstElement element;
+  /* pads */
+  GstPad *srcpad;
+
+  /* current file details */
+  gchar  *currentfilename;
+  GSList *listptr;
+
+  /* mapping parameters */
+  gint fd;
+  gulong size;    /* how long is the file? */
+  guchar *map;    /* where the file is mapped to */
+
+  gint curfileindex; /* how many files have we done so far */
+
+  gboolean have_newmedia_events; /* tunable parameter to say whether new media
+                                   disconts should be generated */
+
+  gboolean new_seek;
+};
+
+struct _GstMultiFileSrcClass {
+  GstElementClass parent_class;
+
+  void (*new_file)  (GstMultiFileSrc *multifilesrc, gchar *newfilename);
+};
+
+GType gst_multifilesrc_get_type(void);
+
+G_END_DECLS
+
+#endif /* __GST_MULTIFILESRC_H__ */
diff --git a/gst/oldcore/gstpipefilter.c b/gst/oldcore/gstpipefilter.c
new file mode 100644 (file)
index 0000000..f802124
--- /dev/null
@@ -0,0 +1,356 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ *                    2000 Wim Taymans <wtay@chello.be>
+ *
+ * gstpipefilter.c:
+ *
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include "../gst-i18n-lib.h"
+#include "gstpipefilter.h"
+
+static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS_ANY);
+
+static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS_ANY);
+
+GST_DEBUG_CATEGORY_STATIC (gst_pipefilter_debug);
+#define GST_CAT_DEFAULT gst_pipefilter_debug
+
+GstElementDetails gst_pipefilter_details = GST_ELEMENT_DETAILS ("Pipefilter",
+    "Filter",
+    "Interoperate with an external program using stdin and stdout",
+    "Erik Walthinsen <omega@cse.ogi.edu>, "
+    "Wim Taymans <wim.taymans@chello.be>");
+
+
+/* Pipefilter signals and args */
+enum
+{
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+enum
+{
+  ARG_0,
+  ARG_COMMAND
+};
+
+
+#define _do_init(bla) \
+    GST_DEBUG_CATEGORY_INIT (gst_pipefilter_debug, "pipefilter", 0, "pipefilter element");
+
+GST_BOILERPLATE_FULL (GstPipefilter, gst_pipefilter, GstElement,
+    GST_TYPE_ELEMENT, _do_init);
+
+static void gst_pipefilter_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_pipefilter_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+
+static GstData *gst_pipefilter_get (GstPad * pad);
+static void gst_pipefilter_chain (GstPad * pad, GstData * _data);
+static gboolean gst_pipefilter_handle_event (GstPad * pad, GstEvent * event);
+
+static GstElementStateReturn gst_pipefilter_change_state (GstElement * element);
+
+static void
+gst_pipefilter_base_init (gpointer g_class)
+{
+  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&srctemplate));
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&sinktemplate));
+  gst_element_class_set_details (gstelement_class, &gst_pipefilter_details);
+}
+static void
+gst_pipefilter_class_init (GstPipefilterClass * klass)
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+
+  gobject_class = (GObjectClass *) klass;
+  gstelement_class = (GstElementClass *) klass;
+
+
+  gobject_class->set_property = gst_pipefilter_set_property;
+  gobject_class->get_property = gst_pipefilter_get_property;
+
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_COMMAND, g_param_spec_string ("command", "command", "command", NULL, G_PARAM_READWRITE));        /* CHECKME */
+
+  gstelement_class->change_state = gst_pipefilter_change_state;
+}
+
+static void
+gst_pipefilter_init (GstPipefilter * pipefilter)
+{
+  GST_FLAG_SET (pipefilter, GST_ELEMENT_DECOUPLED);
+
+  pipefilter->sinkpad =
+      gst_pad_new_from_template (gst_static_pad_template_get (&sinktemplate),
+      "sink");
+  gst_element_add_pad (GST_ELEMENT (pipefilter), pipefilter->sinkpad);
+  gst_pad_set_chain_function (pipefilter->sinkpad, gst_pipefilter_chain);
+
+  pipefilter->srcpad =
+      gst_pad_new_from_template (gst_static_pad_template_get (&srctemplate),
+      "src");
+  gst_element_add_pad (GST_ELEMENT (pipefilter), pipefilter->srcpad);
+  gst_pad_set_get_function (pipefilter->srcpad, gst_pipefilter_get);
+
+  pipefilter->command = NULL;
+  pipefilter->curoffset = 0;
+  pipefilter->bytes_per_read = 4096;
+  pipefilter->seq = 0;
+}
+
+static gboolean
+gst_pipefilter_handle_event (GstPad * pad, GstEvent * event)
+{
+  GstPipefilter *pipefilter;
+
+  pipefilter = GST_PIPEFILTER (gst_pad_get_parent (pad));
+
+  GST_DEBUG ("pipefilter: %s received event", GST_ELEMENT_NAME (pipefilter));
+
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_EOS:
+      if (close (pipefilter->fdin[1]) < 0)
+        perror ("close");
+      if (close (pipefilter->fdout[0]) < 0)
+        perror ("close");
+      break;
+    default:
+      break;
+  }
+
+  gst_pad_event_default (pad, event);
+
+  return TRUE;
+}
+
+static GstData *
+gst_pipefilter_get (GstPad * pad)
+{
+  GstPipefilter *pipefilter;
+  GstBuffer *newbuf;
+  glong readbytes;
+
+  pipefilter = GST_PIPEFILTER (gst_pad_get_parent (pad));
+
+  /* create the buffer */
+  /* FIXME: should eventually use a bufferpool for this */
+  newbuf = gst_buffer_new ();
+  g_return_val_if_fail (newbuf, NULL);
+
+  /* allocate the space for the buffer data */
+  GST_BUFFER_DATA (newbuf) = g_malloc (pipefilter->bytes_per_read);
+  g_return_val_if_fail (GST_BUFFER_DATA (newbuf) != NULL, NULL);
+
+  /* read it in from the file */
+  GST_DEBUG ("attemting to read %ld bytes", pipefilter->bytes_per_read);
+  readbytes =
+      read (pipefilter->fdout[0], GST_BUFFER_DATA (newbuf),
+      pipefilter->bytes_per_read);
+  GST_DEBUG ("read %ld bytes", readbytes);
+  if (readbytes < 0) {
+    GST_ELEMENT_ERROR (pipefilter, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
+    return NULL;
+  }
+  /* if we didn't get as many bytes as we asked for, we're at EOF */
+  if (readbytes == 0) {
+    return GST_DATA (gst_event_new (GST_EVENT_EOS));
+
+  }
+
+  GST_BUFFER_OFFSET (newbuf) = pipefilter->curoffset;
+  GST_BUFFER_SIZE (newbuf) = readbytes;
+  pipefilter->curoffset += readbytes;
+
+  return GST_DATA (newbuf);
+}
+
+static void
+gst_pipefilter_chain (GstPad * pad, GstData * _data)
+{
+  GstBuffer *buf;
+  GstPipefilter *pipefilter;
+  glong writebytes;
+  guchar *data;
+  gulong size;
+
+  g_return_if_fail (pad != NULL);
+  g_return_if_fail (GST_IS_PAD (pad));
+
+  if (GST_IS_EVENT (_data)) {
+    gst_pipefilter_handle_event (pad, GST_EVENT (_data));
+    return;
+  }
+
+  pipefilter = GST_PIPEFILTER (gst_pad_get_parent (pad));
+
+  buf = GST_BUFFER (_data);
+  data = GST_BUFFER_DATA (buf);
+  size = GST_BUFFER_SIZE (buf);
+
+  GST_DEBUG ("attemting to write %ld bytes", size);
+  writebytes = write (pipefilter->fdin[1], data, size);
+  GST_DEBUG ("written %ld bytes", writebytes);
+  if (writebytes < 0) {
+    GST_ELEMENT_ERROR (pipefilter, RESOURCE, WRITE, (NULL), GST_ERROR_SYSTEM);
+    return;
+  }
+  gst_buffer_unref (buf);
+}
+
+static void
+gst_pipefilter_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstPipefilter *pipefilter;
+
+  /* it's not null if we got it, but it might not be ours */
+  g_return_if_fail (GST_IS_PIPEFILTER (object));
+  pipefilter = GST_PIPEFILTER (object);
+
+  switch (prop_id) {
+    case ARG_COMMAND:
+      pipefilter->orig_command = g_strdup (g_value_get_string (value));
+      pipefilter->command = g_strsplit (g_value_get_string (value), " ", 0);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_pipefilter_get_property (GObject * object, guint prop_id, GValue * value,
+    GParamSpec * pspec)
+{
+  GstPipefilter *pipefilter;
+
+  /* it's not null if we got it, but it might not be ours */
+  g_return_if_fail (GST_IS_PIPEFILTER (object));
+  pipefilter = GST_PIPEFILTER (object);
+
+  switch (prop_id) {
+    case ARG_COMMAND:
+      g_value_set_string (value, pipefilter->orig_command);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+/* open the file, necessary to go to RUNNING state */
+static gboolean
+gst_pipefilter_open_file (GstPipefilter * src)
+{
+  g_return_val_if_fail (!GST_FLAG_IS_SET (src, GST_PIPEFILTER_OPEN), FALSE);
+
+  pipe (src->fdin);
+  pipe (src->fdout);
+
+  if ((src->childpid = fork ()) == -1) {
+    GST_ELEMENT_ERROR (src, RESOURCE, TOO_LAZY, (NULL), GST_ERROR_SYSTEM);
+    return FALSE;
+  }
+
+  if (src->childpid == 0) {
+    close (src->fdin[1]);
+    close (src->fdout[0]);
+    /* child */
+    dup2 (src->fdin[0], STDIN_FILENO);  /* set the childs input stream */
+    dup2 (src->fdout[1], STDOUT_FILENO);        /* set the childs output stream */
+    execvp (src->command[0], &src->command[0]);
+    /* will only be reached if execvp has an error */
+    GST_ELEMENT_ERROR (src, RESOURCE, TOO_LAZY, (NULL), GST_ERROR_SYSTEM);
+    return FALSE;
+
+  } else {
+    close (src->fdin[0]);
+    close (src->fdout[1]);
+  }
+
+  GST_FLAG_SET (src, GST_PIPEFILTER_OPEN);
+  return TRUE;
+}
+
+/* close the file */
+static void
+gst_pipefilter_close_file (GstPipefilter * src)
+{
+  g_return_if_fail (GST_FLAG_IS_SET (src, GST_PIPEFILTER_OPEN));
+
+  /* close the file */
+  close (src->fdout[0]);
+  close (src->fdout[1]);
+  close (src->fdin[0]);
+  close (src->fdin[1]);
+
+  /* zero out a lot of our state */
+  src->curoffset = 0;
+  src->seq = 0;
+
+  GST_FLAG_UNSET (src, GST_PIPEFILTER_OPEN);
+}
+
+static GstElementStateReturn
+gst_pipefilter_change_state (GstElement * element)
+{
+  g_return_val_if_fail (GST_IS_PIPEFILTER (element), FALSE);
+
+  /* if going down into NULL state, close the file if it's open */
+  if (GST_STATE_PENDING (element) == GST_STATE_NULL) {
+    if (GST_FLAG_IS_SET (element, GST_PIPEFILTER_OPEN))
+      gst_pipefilter_close_file (GST_PIPEFILTER (element));
+    /* otherwise (READY or higher) we need to open the file */
+  } else {
+    if (!GST_FLAG_IS_SET (element, GST_PIPEFILTER_OPEN)) {
+      if (!gst_pipefilter_open_file (GST_PIPEFILTER (element)))
+        return GST_STATE_FAILURE;
+    }
+  }
+
+  if (GST_ELEMENT_CLASS (parent_class)->change_state)
+    return GST_ELEMENT_CLASS (parent_class)->change_state (element);
+  return GST_STATE_SUCCESS;
+}
diff --git a/gst/oldcore/gstpipefilter.h b/gst/oldcore/gstpipefilter.h
new file mode 100644 (file)
index 0000000..08c3a47
--- /dev/null
@@ -0,0 +1,81 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ *                    2000 Wim Taymans <wtay@chello.be>
+ *
+ * gstpipefilter.h: 
+ *
+ * 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.
+ */
+
+
+#ifndef __GST_PIPEFILTER_H__
+#define __GST_PIPEFILTER_H__
+
+#include <sys/types.h>
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+
+#define GST_TYPE_PIPEFILTER \
+  (gst_pipefilter_get_type())
+#define GST_PIPEFILTER(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PIPEFILTER,GstPipefilter))
+#define GST_PIPEFILTER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PIPEFILTER,GstPipefilterClass))
+#define GST_IS_PIPEFILTER(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PIPEFILTER))
+#define GST_IS_PIPEFILTER_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PIPEFILTER))
+
+typedef enum {
+  GST_PIPEFILTER_OPEN          = GST_ELEMENT_FLAG_LAST,
+
+  GST_PIPEFILTER_FLAG_LAST     = GST_ELEMENT_FLAG_LAST + 2
+} GstPipeFilterFlags;
+
+typedef struct _GstPipefilter GstPipefilter;
+typedef struct _GstPipefilterClass GstPipefilterClass;
+
+struct _GstPipefilter {
+  GstElement element;
+
+  GstPad *sinkpad;
+  GstPad *srcpad;
+
+  /* command */
+  gchar **command;
+  gchar *orig_command;
+  /* fd */
+  gint fdout[2];
+  gint fdin[2];
+  pid_t   childpid;
+
+  gulong curoffset;                     /* current offset in file */
+  gulong bytes_per_read;                /* bytes per read */
+
+  gulong seq;                           /* buffer sequence number */
+};
+
+struct _GstPipefilterClass {
+  GstElementClass parent_class;
+};
+
+GType gst_pipefilter_get_type(void);
+
+G_END_DECLS
+
+#endif /* __GST_PIPEFILTER_H__ */
diff --git a/gst/oldcore/gstshaper.c b/gst/oldcore/gstshaper.c
new file mode 100644 (file)
index 0000000..c14ab36
--- /dev/null
@@ -0,0 +1,373 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ *                    2000 Wim Taymans <wtay@chello.be>
+ *
+ * gstshaper.c: 
+ *
+ * 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 <stdlib.h>
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include "gstshaper.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_shaper_debug);
+#define GST_CAT_DEFAULT gst_shaper_debug
+
+GstElementDetails gst_shaper_details = GST_ELEMENT_DETAILS ("Shaper",
+    "Generic",
+    "Synchronizes streams on different pads",
+    "Wim Taymans <wim.taymans@chello.be>");
+
+
+/* Shaper signals and args */
+enum
+{
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+enum
+{
+  ARG_0,
+  ARG_POLICY,
+  ARG_SILENT,
+  ARG_LAST_MESSAGE
+};
+
+typedef struct
+{
+  GstPad *sinkpad;
+  GstPad *srcpad;
+  GstBuffer *buffer;
+}
+GstShaperConnection;
+
+GstStaticPadTemplate shaper_src_template = GST_STATIC_PAD_TEMPLATE ("src%d",
+    GST_PAD_SRC,
+    GST_PAD_SOMETIMES,
+    GST_STATIC_CAPS_ANY);
+
+GstStaticPadTemplate shaper_sink_template = GST_STATIC_PAD_TEMPLATE ("sink%d",
+    GST_PAD_SINK,
+    GST_PAD_REQUEST,
+    GST_STATIC_CAPS_ANY);
+
+#define GST_TYPE_SHAPER_POLICY (gst_shaper_policy_get_type())
+static GType
+gst_shaper_policy_get_type (void)
+{
+  static GType shaper_policy_type = 0;
+  static GEnumValue shaper_policy[] = {
+    {SHAPER_POLICY_TIMESTAMPS, "1", "sync on timestamps"},
+    {SHAPER_POLICY_BUFFERSIZE, "2", "sync on buffer size"},
+    {0, NULL, NULL},
+  };
+
+  if (!shaper_policy_type) {
+    shaper_policy_type =
+        g_enum_register_static ("GstShaperPolicy", shaper_policy);
+  }
+  return shaper_policy_type;
+}
+
+#define _do_init(bla) \
+    GST_DEBUG_CATEGORY_INIT (gst_shaper_debug, "shaper", 0, "shaper element");
+
+GST_BOILERPLATE_FULL (GstShaper, gst_shaper, GstElement, GST_TYPE_ELEMENT,
+    _do_init);
+
+static void gst_shaper_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_shaper_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+
+static GstPad *gst_shaper_request_new_pad (GstElement * element,
+    GstPadTemplate * templ, const gchar * unused);
+
+static void gst_shaper_loop (GstElement * element);
+
+
+static void
+gst_shaper_base_init (gpointer g_class)
+{
+  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_set_details (gstelement_class, &gst_shaper_details);
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&shaper_src_template));
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&shaper_sink_template));
+}
+
+static void
+gst_shaper_class_init (GstShaperClass * klass)
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+
+  gobject_class = (GObjectClass *) klass;
+  gstelement_class = (GstElementClass *) klass;
+
+  gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_shaper_set_property);
+  gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_shaper_get_property);
+
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_POLICY,
+      g_param_spec_enum ("policy", "Policy", "Shaper policy",
+          GST_TYPE_SHAPER_POLICY, SHAPER_POLICY_TIMESTAMPS, G_PARAM_READWRITE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SILENT,
+      g_param_spec_boolean ("silent", "silent", "silent",
+          FALSE, G_PARAM_READWRITE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
+      g_param_spec_string ("last-message", "last-message", "last-message",
+          NULL, G_PARAM_READABLE));
+
+  gstelement_class->request_new_pad =
+      GST_DEBUG_FUNCPTR (gst_shaper_request_new_pad);
+}
+
+static GstCaps *
+gst_shaper_getcaps (GstPad * pad)
+{
+  GstPad *otherpad;
+  GstShaperConnection *connection;
+
+  connection = gst_pad_get_element_private (pad);
+
+  otherpad =
+      (pad == connection->srcpad ? connection->sinkpad : connection->srcpad);
+
+  if (GST_PAD_PEER (otherpad)) {
+    return gst_pad_get_caps (GST_PAD_PEER (otherpad));
+  } else {
+    return gst_caps_new_any ();
+  }
+}
+
+static GList *
+gst_shaper_get_internal_link (GstPad * pad)
+{
+  GList *res = NULL;
+  GstShaperConnection *connection;
+  GstPad *otherpad;
+
+  connection = gst_pad_get_element_private (pad);
+
+  otherpad =
+      (pad == connection->srcpad ? connection->sinkpad : connection->srcpad);
+
+  res = g_list_prepend (res, otherpad);
+
+  return res;
+}
+
+static GstPadLinkReturn
+gst_shaper_link (GstPad * pad, const GstCaps * caps)
+{
+  GstPad *otherpad;
+  GstShaperConnection *connection;
+
+  connection = gst_pad_get_element_private (pad);
+
+  otherpad =
+      (pad == connection->srcpad ? connection->sinkpad : connection->srcpad);
+
+  return gst_pad_try_set_caps (otherpad, caps);
+}
+
+static GstShaperConnection *
+gst_shaper_create_connection (GstShaper * shaper)
+{
+  GstShaperConnection *connection;
+  gchar *padname;
+
+  shaper->nconnections++;
+
+  connection = g_new0 (GstShaperConnection, 1);
+
+  padname = g_strdup_printf ("sink%d", shaper->nconnections);
+  connection->sinkpad =
+      gst_pad_new_from_template (gst_static_pad_template_get
+      (&shaper_sink_template), padname);
+  g_free (padname);
+  gst_pad_set_getcaps_function (connection->sinkpad, gst_shaper_getcaps);
+  gst_pad_set_internal_link_function (connection->sinkpad,
+      gst_shaper_get_internal_link);
+  gst_pad_set_link_function (connection->sinkpad, gst_shaper_link);
+  gst_pad_set_element_private (connection->sinkpad, connection);
+  gst_element_add_pad (GST_ELEMENT (shaper), connection->sinkpad);
+
+  padname = g_strdup_printf ("src%d", shaper->nconnections);
+  connection->srcpad =
+      gst_pad_new_from_template (gst_static_pad_template_get
+      (&shaper_src_template), padname);
+  g_free (padname);
+  gst_pad_set_getcaps_function (connection->srcpad, gst_shaper_getcaps);
+  gst_pad_set_internal_link_function (connection->srcpad,
+      gst_shaper_get_internal_link);
+  gst_pad_set_link_function (connection->srcpad, gst_shaper_link);
+  gst_pad_set_element_private (connection->srcpad, connection);
+  gst_element_add_pad (GST_ELEMENT (shaper), connection->srcpad);
+
+  shaper->connections = g_slist_prepend (shaper->connections, connection);
+
+  return connection;
+}
+
+static GstPad *
+gst_shaper_request_new_pad (GstElement * element, GstPadTemplate * templ,
+    const gchar * unused)
+{
+  GstShaper *shaper = GST_SHAPER (element);
+  GstShaperConnection *connection;
+
+  connection = gst_shaper_create_connection (shaper);
+
+  return connection->sinkpad;
+}
+
+static void
+gst_shaper_init (GstShaper * shaper)
+{
+  gst_element_set_loop_function (GST_ELEMENT (shaper), gst_shaper_loop);
+
+  shaper->policy = SHAPER_POLICY_TIMESTAMPS;
+  shaper->connections = NULL;
+  shaper->nconnections = 0;
+  shaper->silent = FALSE;
+  shaper->last_message = NULL;
+}
+
+static void
+gst_shaper_loop (GstElement * element)
+{
+  GstShaper *shaper;
+  GSList *connections;
+  gboolean eos = TRUE;
+  GstShaperConnection *min = NULL;
+
+  shaper = GST_SHAPER (element);
+
+  /* first make sure we have a buffer on all pads */
+  connections = shaper->connections;
+  while (connections) {
+    GstShaperConnection *connection = (GstShaperConnection *) connections->data;
+
+    /* try to fill a connection without a buffer on a pad that is
+     * active */
+    if (connection->buffer == NULL && GST_PAD_IS_USABLE (connection->sinkpad)) {
+      GstBuffer *buffer;
+
+      buffer = GST_BUFFER (gst_pad_pull (connection->sinkpad));
+
+      /* events are simply pushed ASAP */
+      if (GST_IS_EVENT (buffer)) {
+        /* save event type as it will be unreffed after the next push */
+        GstEventType type = GST_EVENT_TYPE (buffer);
+
+        gst_pad_push (connection->srcpad, GST_DATA (buffer));
+
+        switch (type) {
+            /* on EOS we disable the pad so that we don't pull on
+             * it again and never get more data */
+          case GST_EVENT_EOS:
+            gst_pad_set_active (connection->sinkpad, FALSE);
+            break;
+          default:
+            break;
+        }
+      } else {
+        /* we store the buffer */
+        connection->buffer = buffer;
+      }
+    }
+    /* FIXME policy stuff goes here */
+    /* find connection with lowest timestamp */
+    if (min == NULL || (connection->buffer != NULL &&
+            (GST_BUFFER_TIMESTAMP (connection->buffer) <
+                GST_BUFFER_TIMESTAMP (min->buffer)))) {
+      min = connection;
+    }
+    connections = g_slist_next (connections);
+  }
+  /* if we have a connection with a buffer, push it */
+  if (min != NULL && min->buffer) {
+    gst_pad_push (min->srcpad, GST_DATA (min->buffer));
+    min->buffer = NULL;
+    /* since we pushed a buffer, it's not EOS */
+    eos = FALSE;
+  }
+
+  if (eos) {
+    gst_element_set_eos (element);
+  }
+}
+
+static void
+gst_shaper_set_property (GObject * object, guint prop_id, const GValue * value,
+    GParamSpec * pspec)
+{
+  GstShaper *shaper;
+
+  /* it's not null if we got it, but it might not be ours */
+  g_return_if_fail (GST_IS_SHAPER (object));
+
+  shaper = GST_SHAPER (object);
+
+  switch (prop_id) {
+    case ARG_POLICY:
+      shaper->policy = g_value_get_enum (value);
+      break;
+    case ARG_SILENT:
+      shaper->silent = g_value_get_boolean (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_shaper_get_property (GObject * object, guint prop_id, GValue * value,
+    GParamSpec * pspec)
+{
+  GstShaper *shaper;
+
+  /* it's not null if we got it, but it might not be ours */
+  g_return_if_fail (GST_IS_SHAPER (object));
+
+  shaper = GST_SHAPER (object);
+
+  switch (prop_id) {
+    case ARG_POLICY:
+      g_value_set_enum (value, shaper->policy);
+      break;
+    case ARG_SILENT:
+      g_value_set_boolean (value, shaper->silent);
+      break;
+    case ARG_LAST_MESSAGE:
+      g_value_set_string (value, shaper->last_message);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
diff --git a/gst/oldcore/gstshaper.h b/gst/oldcore/gstshaper.h
new file mode 100644 (file)
index 0000000..1fe84e5
--- /dev/null
@@ -0,0 +1,72 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ *                    2000 Wim Taymans <wtay@chello.be>
+ *
+ * gstshaper.h: 
+ *
+ * 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.
+ */
+
+
+#ifndef __GST_SHAPER_H__
+#define __GST_SHAPER_H__
+
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+
+#define GST_TYPE_SHAPER \
+  (gst_shaper_get_type())
+#define GST_SHAPER(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SHAPER,GstShaper))
+#define GST_SHAPER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SHAPER,GstShaperClass))
+#define GST_IS_SHAPER(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SHAPER))
+#define GST_IS_SHAPER_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SHAPER))
+
+typedef enum {
+  SHAPER_POLICY_TIMESTAMPS = 1,
+  SHAPER_POLICY_BUFFERSIZE
+} GstShaperPolicyType;
+
+typedef struct _GstShaper GstShaper;
+typedef struct _GstShaperClass GstShaperClass;
+
+struct _GstShaper {
+  GstElement    element;
+
+  GSList       *connections;
+  gint          nconnections;
+
+  GstShaperPolicyType  policy;
+
+  gboolean      silent;
+  gchar        *last_message;
+};
+
+struct _GstShaperClass {
+  GstElementClass parent_class;
+};
+
+GType          gst_shaper_get_type     (void);
+
+G_END_DECLS
+
+#endif /* __GST_SHAPER_H__ */
diff --git a/gst/oldcore/gststatistics.c b/gst/oldcore/gststatistics.c
new file mode 100644 (file)
index 0000000..ef6cca3
--- /dev/null
@@ -0,0 +1,416 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ *                    2000 Wim Taymans <wtay@chello.be>
+ *
+ * gststatistics.c: 
+ *
+ * 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.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include "gststatistics.h"
+
+static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS_ANY);
+
+static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS_ANY);
+
+GST_DEBUG_CATEGORY_STATIC (gst_statistics_debug);
+#define GST_CAT_DEFAULT gst_statistics_debug
+
+GstElementDetails gst_statistics_details = GST_ELEMENT_DETAILS ("Statistics",
+    "Generic",
+    "Statistics on buffers/bytes/events",
+    "David I. Lehn <dlehn@users.sourceforge.net>");
+
+
+/* Statistics signals and args */
+enum
+{
+  SIGNAL_UPDATE,
+  LAST_SIGNAL
+};
+
+enum
+{
+  ARG_0,
+  ARG_BUFFERS,
+  ARG_BYTES,
+  ARG_EVENTS,
+  ARG_BUFFER_UPDATE_FREQ,
+  ARG_BYTES_UPDATE_FREQ,
+  ARG_EVENT_UPDATE_FREQ,
+  ARG_UPDATE_ON_EOS,
+  ARG_UPDATE,
+  ARG_SILENT
+};
+
+
+#define _do_init(bla) \
+    GST_DEBUG_CATEGORY_INIT (gst_statistics_debug, "statistics", 0, "statistics element");
+
+GST_BOILERPLATE_FULL (GstStatistics, gst_statistics, GstElement,
+    GST_TYPE_ELEMENT, _do_init);
+
+static void gst_statistics_finalize (GObject * object);
+static void gst_statistics_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_statistics_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+
+static void gst_statistics_chain (GstPad * pad, GstData * _data);
+static void gst_statistics_reset (GstStatistics * statistics);
+static void gst_statistics_print (GstStatistics * statistics);
+
+static guint gst_statistics_signals[LAST_SIGNAL] = { 0, };
+
+static stats zero_stats = { 0, };
+
+
+static void
+gst_statistics_base_init (gpointer g_class)
+{
+  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&srctemplate));
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&sinktemplate));
+  gst_element_class_set_details (gstelement_class, &gst_statistics_details);
+}
+
+static void
+gst_statistics_finalize (GObject * object)
+{
+  GstStatistics *statistics;
+
+  statistics = GST_STATISTICS (object);
+
+  if (statistics->timer)
+    g_timer_destroy (statistics->timer);
+
+  if (statistics->last_timer)
+    g_timer_destroy (statistics->last_timer);
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gst_statistics_class_init (GstStatisticsClass * klass)
+{
+  GObjectClass *gobject_class;
+
+  gobject_class = G_OBJECT_CLASS (klass);
+
+  gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_statistics_set_property);
+  gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_statistics_get_property);
+
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BUFFERS,
+      g_param_spec_int64 ("buffers", "buffers", "total buffers count",
+          0, G_MAXINT64, 0, G_PARAM_READABLE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BYTES,
+      g_param_spec_int64 ("bytes", "bytes", "total bytes count",
+          0, G_MAXINT64, 0, G_PARAM_READABLE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_EVENTS,
+      g_param_spec_int64 ("events", "events", "total event count",
+          0, G_MAXINT64, 0, G_PARAM_READABLE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass),
+      ARG_BUFFER_UPDATE_FREQ, g_param_spec_int64 ("buffer_update_freq",
+          "buffer update freq", "buffer update frequency", 0, G_MAXINT64, 0,
+          G_PARAM_READWRITE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass),
+      ARG_BYTES_UPDATE_FREQ, g_param_spec_int64 ("bytes_update_freq",
+          "bytes update freq", "bytes update frequency", 0, G_MAXINT64, 0,
+          G_PARAM_READWRITE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass),
+      ARG_EVENT_UPDATE_FREQ, g_param_spec_int64 ("event_update_freq",
+          "event update freq", "event update frequency", 0, G_MAXINT64, 0,
+          G_PARAM_READWRITE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_UPDATE_ON_EOS,
+      g_param_spec_boolean ("update_on_eos", "update on EOS",
+          "update on EOS event", TRUE, G_PARAM_READWRITE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_UPDATE,
+      g_param_spec_boolean ("update", "update", "update", TRUE,
+          G_PARAM_READWRITE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SILENT,
+      g_param_spec_boolean ("silent", "silent", "silent", TRUE,
+          G_PARAM_READWRITE));
+
+  gst_statistics_signals[SIGNAL_UPDATE] =
+      g_signal_new ("update", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
+      G_STRUCT_OFFSET (GstStatisticsClass, update), NULL, NULL,
+      g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+
+  gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_statistics_finalize);
+}
+
+static void
+gst_statistics_init (GstStatistics * statistics)
+{
+  statistics->sinkpad =
+      gst_pad_new_from_template (gst_static_pad_template_get (&sinktemplate),
+      "sink");
+  gst_element_add_pad (GST_ELEMENT (statistics), statistics->sinkpad);
+  gst_pad_set_chain_function (statistics->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_statistics_chain));
+
+  statistics->srcpad =
+      gst_pad_new_from_template (gst_static_pad_template_get (&srctemplate),
+      "src");
+  gst_element_add_pad (GST_ELEMENT (statistics), statistics->srcpad);
+
+  statistics->timer = NULL;
+  statistics->last_timer = NULL;
+  gst_statistics_reset (statistics);
+}
+
+static void
+gst_statistics_reset (GstStatistics * statistics)
+{
+  g_return_if_fail (statistics != NULL);
+  g_return_if_fail (GST_IS_STATISTICS (statistics));
+
+  statistics->stats.buffers = 0;
+  statistics->stats.bytes = 0;
+  statistics->stats.events = 0;
+
+  statistics->last_stats.buffers = 0;
+  statistics->last_stats.bytes = 0;
+  statistics->last_stats.events = 0;
+
+  statistics->update_count.buffers = 0;
+  statistics->update_count.bytes = 0;
+  statistics->update_count.events = 0;
+
+  statistics->update_freq.buffers = 0;
+  statistics->update_freq.bytes = 0;
+  statistics->update_freq.events = 0;
+
+  statistics->update_on_eos = TRUE;
+  statistics->update = TRUE;
+  statistics->silent = FALSE;
+
+  if (!statistics->timer) {
+    statistics->timer = g_timer_new ();
+  }
+  if (!statistics->last_timer) {
+    statistics->last_timer = g_timer_new ();
+  }
+}
+
+static void
+print_stats (gboolean first, const gchar * name, const gchar * type,
+    stats * base, stats * final, double time)
+{
+  const gchar *header0 = "statistics";
+  const gchar *headerN = "          ";
+  stats delta;
+
+  delta.buffers = final->buffers - base->buffers;
+  delta.bytes = final->bytes - base->bytes;
+  delta.events = final->events - base->events;
+
+  g_print ("%s: (%s) %s: s:%g buffers:%" G_GINT64_FORMAT
+      " bytes:%" G_GINT64_FORMAT
+      " events:%" G_GINT64_FORMAT "\n",
+      first ? header0 : headerN,
+      name, type, time, final->buffers, final->bytes, final->events);
+  g_print ("%s: (%s) %s: buf/s:%g B/s:%g e/s:%g B/buf:%g\n",
+      headerN,
+      name, type,
+      delta.buffers / time,
+      delta.bytes / time,
+      delta.events / time, ((double) delta.bytes / (double) delta.buffers));
+}
+
+static void
+gst_statistics_print (GstStatistics * statistics)
+{
+  const gchar *name;
+  double elapsed;
+  double last_elapsed;
+
+  g_return_if_fail (statistics != NULL);
+  g_return_if_fail (GST_IS_STATISTICS (statistics));
+
+  name = gst_object_get_name (GST_OBJECT (statistics));
+  if (!name) {
+    name = "";
+  }
+
+  elapsed = g_timer_elapsed (statistics->timer, NULL);
+  last_elapsed = g_timer_elapsed (statistics->last_timer, NULL);
+
+  print_stats (1, name, "total", &zero_stats, &statistics->stats, elapsed);
+  print_stats (0, name, "last", &statistics->last_stats, &statistics->stats,
+      last_elapsed);
+  statistics->last_stats = statistics->stats;
+  g_timer_reset (statistics->last_timer);
+}
+
+static void
+gst_statistics_chain (GstPad * pad, GstData * _data)
+{
+  GstBuffer *buf = GST_BUFFER (_data);
+  GstStatistics *statistics;
+  gboolean update = FALSE;
+
+  g_return_if_fail (pad != NULL);
+  g_return_if_fail (GST_IS_PAD (pad));
+  g_return_if_fail (buf != NULL);
+
+  statistics = GST_STATISTICS (gst_pad_get_parent (pad));
+
+  if (GST_IS_EVENT (buf)) {
+    GstEvent *event = GST_EVENT (buf);
+
+    statistics->stats.events += 1;
+    if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
+      gst_element_set_eos (GST_ELEMENT (statistics));
+      if (statistics->update_on_eos) {
+        update = TRUE;
+      }
+    }
+    if (statistics->update_freq.events) {
+      statistics->update_count.events += 1;
+      if (statistics->update_count.events == statistics->update_freq.events) {
+        statistics->update_count.events = 0;
+        update = TRUE;
+      }
+    }
+  } else {
+    statistics->stats.buffers += 1;
+    if (statistics->update_freq.buffers) {
+      statistics->update_count.buffers += 1;
+      if (statistics->update_count.buffers == statistics->update_freq.buffers) {
+        statistics->update_count.buffers = 0;
+        update = TRUE;
+      }
+    }
+
+    statistics->stats.bytes += GST_BUFFER_SIZE (buf);
+    if (statistics->update_freq.bytes) {
+      statistics->update_count.bytes += GST_BUFFER_SIZE (buf);
+      if (statistics->update_count.bytes >= statistics->update_freq.bytes) {
+        statistics->update_count.bytes = 0;
+        update = TRUE;
+      }
+    }
+  }
+
+  if (update) {
+    if (statistics->update) {
+      GST_DEBUG ("[%s]: pre update emit", GST_ELEMENT_NAME (statistics));
+      g_signal_emit (G_OBJECT (statistics),
+          gst_statistics_signals[SIGNAL_UPDATE], 0);
+      GST_DEBUG ("[%s]: post update emit", GST_ELEMENT_NAME (statistics));
+    }
+    if (!statistics->silent) {
+      gst_statistics_print (statistics);
+    }
+  }
+  gst_pad_push (statistics->srcpad, GST_DATA (buf));
+}
+
+static void
+gst_statistics_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstStatistics *statistics;
+
+  /* it's not null if we got it, but it might not be ours */
+  g_return_if_fail (GST_IS_STATISTICS (object));
+
+  statistics = GST_STATISTICS (object);
+
+  switch (prop_id) {
+    case ARG_BUFFER_UPDATE_FREQ:
+      statistics->update_freq.buffers = g_value_get_int64 (value);
+      break;
+    case ARG_BYTES_UPDATE_FREQ:
+      statistics->update_freq.bytes = g_value_get_int64 (value);
+      break;
+    case ARG_EVENT_UPDATE_FREQ:
+      statistics->update_freq.events = g_value_get_int64 (value);
+      break;
+    case ARG_UPDATE_ON_EOS:
+      statistics->update_on_eos = g_value_get_boolean (value);
+      break;
+    case ARG_UPDATE:
+      statistics->update = g_value_get_boolean (value);
+      break;
+    case ARG_SILENT:
+      statistics->silent = g_value_get_boolean (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_statistics_get_property (GObject * object, guint prop_id, GValue * value,
+    GParamSpec * pspec)
+{
+  GstStatistics *statistics;
+
+  /* it's not null if we got it, but it might not be ours */
+  g_return_if_fail (GST_IS_STATISTICS (object));
+
+  statistics = GST_STATISTICS (object);
+
+  switch (prop_id) {
+    case ARG_BUFFERS:
+      g_value_set_int64 (value, statistics->stats.buffers);
+      break;
+    case ARG_BYTES:
+      g_value_set_int64 (value, statistics->stats.bytes);
+      break;
+    case ARG_EVENTS:
+      g_value_set_int64 (value, statistics->stats.events);
+      break;
+    case ARG_BUFFER_UPDATE_FREQ:
+      g_value_set_int64 (value, statistics->update_freq.buffers);
+      break;
+    case ARG_BYTES_UPDATE_FREQ:
+      g_value_set_int64 (value, statistics->update_freq.bytes);
+      break;
+    case ARG_EVENT_UPDATE_FREQ:
+      g_value_set_int64 (value, statistics->update_freq.events);
+      break;
+    case ARG_UPDATE_ON_EOS:
+      g_value_set_boolean (value, statistics->update_on_eos);
+      break;
+    case ARG_UPDATE:
+      g_value_set_boolean (value, statistics->update);
+      break;
+    case ARG_SILENT:
+      g_value_set_boolean (value, statistics->silent);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
diff --git a/gst/oldcore/gststatistics.h b/gst/oldcore/gststatistics.h
new file mode 100644 (file)
index 0000000..4c1ab57
--- /dev/null
@@ -0,0 +1,84 @@
+/* GStreamer
+ * Copyright (C) 2001 David I. Lehn <dlehn@users.sourceforge.net>
+ *
+ * gststatistics.h: 
+ *
+ * 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.
+ */
+
+
+#ifndef __GST_STATISTICS_H__
+#define __GST_STATISTICS_H__
+
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+
+#define GST_TYPE_STATISTICS \
+  (gst_statistics_get_type())
+#define GST_STATISTICS(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_STATISTICS,GstStatistics))
+#define GST_STATISTICS_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_STATISTICS,GstStatisticsClass))
+#define GST_IS_STATISTICS(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_STATISTICS))
+#define GST_IS_STATISTICS_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_STATISTICS))
+
+typedef struct _GstStatistics GstStatistics;
+typedef struct _GstStatisticsClass GstStatisticsClass;
+
+typedef struct _stats stats;
+
+struct _stats {
+  gint64 buffers;
+  gint64 bytes;
+  gint64 events;
+};
+
+struct _GstStatistics {
+  GstElement element;
+
+  GstPad *sinkpad;
+  GstPad *srcpad;
+
+  GTimer *timer;
+  GTimer *last_timer;
+
+  stats stats;
+  stats last_stats;
+  stats update_count;
+  stats update_freq;
+
+  gboolean update_on_eos; 
+  gboolean update;
+  gboolean silent;
+};
+
+struct _GstStatisticsClass {
+  GstElementClass parent_class;
+
+  /* signals */
+  void (*update) (GstElement *element);
+};
+
+GType gst_statistics_get_type(void);
+
+G_END_DECLS
+
+#endif /* __GST_STATISTICS_H__ */