--- configure.ac	2005-02-09 14:22:07.188729021 +0100
+++ configure.ac	2005-02-09 14:46:01.493423756 +0100
@@ -408,6 +408,7 @@
 	realmedia \
 	rtjpeg \
 	rtp \
+	scroller \
 	silence \
 	sine \
 	smooth \
@@ -1991,6 +1992,7 @@
 gst/realmedia/Makefile
 gst/rtjpeg/Makefile
 gst/rtp/Makefile
+gst/scroller/Makefile
 gst/silence/Makefile
 gst/sine/Makefile
 gst/smooth/Makefile
--- gst/scroller/gstbouncingscroller.c	1970-01-01 01:00:00.000000000 +0100
+++ gst/scroller/gstbouncingscroller.c	2005-02-09 14:45:18.384195495 +0100
@@ -0,0 +1,158 @@
+/* GStreamer
+ * Copyright (C) 2005 Gergely Nagy <gergely.nagy@neteyes.hu>
+ *
+ * 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 "gstscroller.h"
+#include "gstbouncingscroller.h"
+
+GST_DEBUG_CATEGORY (bouncingscroller_debug);
+#define GST_CAT_DEFAULT bouncingscroller_debug
+
+static GstElementDetails bouncingscroller_details =
+GST_ELEMENT_DETAILS ("Bouncing video scroller",
+		     "Filter/Effect/Video",
+		     "Bouncing video scroller",
+		     "Gergely Nagy <gergely.nagy@neteyes.hu>");
+
+static GstScrollerClass *parent_class = NULL;
+
+void
+gst_bouncingscroller_base_init (gpointer g_class)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_set_details (element_class, &bouncingscroller_details);
+
+  gst_scroller_class_add_pad_templates (element_class);
+}
+
+static gint
+gst_bouncingscroller_get_direction (gint min, gint current, gint max, gint dir)
+{
+  if (max <= min)
+    return 0;
+
+  if (current <= min)
+    return 1;
+  if (current >= max)
+    return -1;
+
+  if (dir == 0) {
+    if (current > min)
+      return -1;
+    else
+      return 1;
+  }
+
+  return dir;
+}
+
+static void
+gst_bouncingscroller_position (GstScroller *scroller)
+{
+  if (scroller->initialised) {
+    if (scroller->iteration >= scroller->speed) {
+      scroller->current_pos.x +=
+	scroller->current_direction.x * scroller->step;
+      scroller->current_pos.y +=
+	scroller->current_direction.y * scroller->step;
+
+      scroller->iteration = 0;
+    }
+  }
+
+  scroller->current_direction.x =
+    gst_bouncingscroller_get_direction (scroller->min_pos.x,
+					scroller->current_pos.x,
+					scroller->max_pos.x,
+					scroller->current_direction.x);
+  scroller->current_direction.y =
+    gst_bouncingscroller_get_direction (scroller->min_pos.y,
+					scroller->current_pos.y,
+					scroller->max_pos.y,
+					scroller->current_direction.y);
+}
+
+void
+gst_bouncingscroller_class_init (GstBouncingScrollerClass *class)
+{
+  GstScrollerClass *scroller = GST_SCROLLER_CLASS (class);
+
+  parent_class = g_type_class_peek_parent (class);
+
+  scroller->position = gst_bouncingscroller_position;
+}
+
+GType
+gst_bouncingscroller_get_type (void)
+{
+  static GType bouncingscroller_type = 0;
+
+  if (!bouncingscroller_type) {
+    static const GTypeInfo bouncingscroller_info = {
+      sizeof (GstBouncingScrollerClass),
+      gst_bouncingscroller_base_init,
+      NULL,
+      (GClassInitFunc) gst_bouncingscroller_class_init,
+      NULL,
+      NULL,
+      sizeof (GstBouncingScroller),
+      0,
+      NULL,
+    };
+
+    bouncingscroller_type = g_type_register_static
+      (GST_TYPE_SCROLLER, "GstBouncingScroller", &bouncingscroller_info, 0);
+  }
+
+  return bouncingscroller_type;
+}
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+  GST_DEBUG_CATEGORY_INIT (bouncingscroller_debug, "bouncingscroller", 0,
+			   "Bouncing video scroller");
+
+  if (!gst_library_load ("gstscroller"))
+    return FALSE;
+
+  return gst_element_register (plugin, "bouncingscroller", GST_RANK_NONE,
+			       GST_TYPE_BOUNCINGSCROLLER);
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+		   GST_VERSION_MINOR,
+		   "bouncingscroller",
+		   "Bouncing video scroller",
+		   plugin_init, VERSION, GST_LICENSE, GST_PACKAGE, GST_ORIGIN)
+
+/*
+ * Local variables:
+ * mode: c
+ * file-style: k&r
+ * c-basic-offset: 2
+ * arch-tag: 4dabb4e1-995f-45b4-9a6a-74b7c15d7dc7
+ * End:
+ */
--- gst/scroller/gstbouncingscroller.h	1970-01-01 01:00:00.000000000 +0100
+++ gst/scroller/gstbouncingscroller.h	2005-02-09 14:45:18.385195338 +0100
@@ -0,0 +1,67 @@
+/* GStreamer
+ * Copyright (C) 2005 Gergely Nagy <gergely.nagy@neteyes.hu>
+ *
+ * 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_BOUNCING_SCROLLER_H__
+#define __GST_BOUNCING_SCROLLER_H__ 1
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_BOUNCINGSCROLLER		\
+  (gst_bouncingscroller_get_type())
+#define GST_BOUNCINGSCROLLER(obj)				\
+  (G_TYPE_CHECK_INSTANCE_CAST					\
+   ((obj), GST_TYPE_BOUNCINGSCROLLER, GstBouncingScroller))
+#define GST_BOUNCINGSCROLLER_CLASS(class)				\
+  (G_TYPE_CHECK_CLASS_CAST((class), GST_TYPE_BOUNCINGSCROLLER,		\
+			   GstBouncingScroller))
+#define GST_BOUNCINGSCROLLER_GET_CLASS(obj)				\
+  (G_TYPE_INSTANCE_GET_CLASS						\
+   ((obj), GST_TYPE_BOUNCINGSCROLLER, GstBouncingScrollerClass))
+#define GST_IS_BOUNCINGSCROLLER(obj)					\
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_BOUNCINGSCROLLER))
+#define GST_IS_BOUNCINGSCROLLER_CLASS(obj)				\
+  (G_TYPE_CHECK_CLASS_TYPE((class), GST_TYPE_BOUNCINGSCROLLER))
+
+typedef struct _GstBouncingScroller      GstBouncingScroller;
+typedef struct _GstBouncingScrollerClass GstBouncingScrollerClass;
+
+struct _GstBouncingScroller {
+  GstScroller scroller;
+};
+
+struct _GstBouncingScrollerClass {
+  GstScrollerClass parent_class;
+};
+
+GType gst_bouncingscroller_get_type(void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif
+
+/*
+ * Local variables:
+ * mode: c
+ * file-style: k&r
+ * c-basic-offset: 2
+ * arch-tag: 86429175-9b08-45d6-8305-018fb29f4802
+ * End:
+ */
--- gst/scroller/gstloopingscroller.c	1970-01-01 01:00:00.000000000 +0100
+++ gst/scroller/gstloopingscroller.c	2005-02-09 14:45:18.385195338 +0100
@@ -0,0 +1,157 @@
+/* GStreamer
+ * Copyright (C) 2005 Gergely Nagy <gergely.nagy@neteyes.hu>
+ *
+ * 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 "gstscroller.h"
+#include "gstloopingscroller.h"
+
+GST_DEBUG_CATEGORY (loopingscroller_debug);
+#define GST_CAT_DEFAULT loopingscroller_debug
+
+static GstElementDetails loopingscroller_details =
+GST_ELEMENT_DETAILS ("Looping video scroller",
+		     "Filter/Effect/Video",
+		     "Looping video scroller",
+		     "Gergely Nagy <gergely.nagy@neteyes.hu>");
+
+static GstScrollerClass *parent_class = NULL;
+
+void
+gst_loopingscroller_base_init (gpointer g_class)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_set_details (element_class, &loopingscroller_details);
+
+  gst_scroller_class_add_pad_templates (element_class);
+}
+
+static void
+gst_loopingscroller_position (GstScroller *scroller)
+{
+  if (!scroller->initialised) {
+    if (scroller->current_pos.x < scroller->max_pos.x)
+      scroller->current_direction.x = 1;
+    else if (scroller->current_pos.x > scroller->min_pos.x)
+      scroller->current_direction.x = -1;
+    else
+      scroller->current_direction.x = 0;
+
+    if (scroller->current_pos.y < scroller->max_pos.y)
+      scroller->current_direction.y = 1;
+    else if (scroller->current_pos.y > scroller->min_pos.y)
+      scroller->current_direction.y = -1;
+    else
+      scroller->current_direction.y = 0;
+
+    return;
+  }
+
+  if (scroller->min_pos.x != scroller->max_pos.x) {
+    scroller->current_pos.x +=
+      scroller->current_direction.x * scroller->step;
+
+    if (scroller->current_pos.x < scroller->min_pos.x &&
+	scroller->current_direction.x == -1)
+      scroller->current_pos.x = scroller->max_pos.x;
+    if (scroller->current_pos.x > scroller->max_pos.x &&
+	scroller->current_direction.x == 1)
+      scroller->current_pos.x = scroller->min_pos.x;
+  }
+
+  if (scroller->min_pos.y != scroller->max_pos.y) {
+    scroller->current_pos.y +=
+      scroller->current_direction.y * scroller->step;
+
+    if (scroller->current_pos.y < scroller->min_pos.y &&
+	scroller->current_direction.y == -1)
+      scroller->current_pos.y = scroller->max_pos.y;
+    if (scroller->current_pos.y > scroller->max_pos.y &&
+	scroller->current_direction.y == 1)
+      scroller->current_pos.y = scroller->min_pos.y;
+  }
+}
+
+void
+gst_loopingscroller_class_init (GstLoopingScrollerClass *class)
+{
+  GstScrollerClass *scroller = GST_SCROLLER_CLASS (class);
+
+  parent_class = g_type_class_peek_parent (class);
+
+  scroller->position = gst_loopingscroller_position;
+}
+
+GType
+gst_loopingscroller_get_type (void)
+{
+  static GType loopingscroller_type = 0;
+
+  if (!loopingscroller_type) {
+    static const GTypeInfo loopingscroller_info = {
+      sizeof (GstLoopingScrollerClass),
+      gst_loopingscroller_base_init,
+      NULL,
+      (GClassInitFunc) gst_loopingscroller_class_init,
+      NULL,
+      NULL,
+      sizeof (GstLoopingScroller),
+      0,
+      NULL,
+    };
+
+    loopingscroller_type = g_type_register_static
+      (GST_TYPE_SCROLLER, "GstLoopingScroller", &loopingscroller_info, 0);
+  }
+
+  return loopingscroller_type;
+}
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+  GST_DEBUG_CATEGORY_INIT (loopingscroller_debug, "loopingscroller", 0,
+			   "Looping video scroller");
+
+  if (!gst_library_load ("gstscroller"))
+    return FALSE;
+
+  return gst_element_register (plugin, "loopingscroller", GST_RANK_NONE,
+      GST_TYPE_LOOPINGSCROLLER);
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+		   GST_VERSION_MINOR,
+		   "loopingscroller",
+		   "Looping video scroller",
+		   plugin_init, VERSION, GST_LICENSE, GST_PACKAGE, GST_ORIGIN)
+
+/*
+ * Local variables:
+ * mode: c
+ * file-style: k&r
+ * c-basic-offset: 2
+ * arch-tag: 2a30a943-ff5d-48db-8030-76f4baf43bfe
+ * End:
+ */
--- gst/scroller/gstloopingscroller.h	1970-01-01 01:00:00.000000000 +0100
+++ gst/scroller/gstloopingscroller.h	2005-02-09 14:45:18.385195338 +0100
@@ -0,0 +1,67 @@
+/* GStreamer
+ * Copyright (C) 2005 Gergely Nagy <gergely.nagy@neteyes.hu>
+ *
+ * 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_LOOPING_SCROLLER_H__
+#define __GST_LOOPING_SCROLLER_H__ 1
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_LOOPINGSCROLLER		\
+  (gst_loopingscroller_get_type())
+#define GST_LOOPINGSCROLLER(obj)				\
+  (G_TYPE_CHECK_INSTANCE_CAST					\
+   ((obj), GST_TYPE_LOOPINGSCROLLER, GstLoopingScroller))
+#define GST_LOOPINGSCROLLER_CLASS(class)				\
+  (G_TYPE_CHECK_CLASS_CAST((class), GST_TYPE_LOOPINGSCROLLER,		\
+			   GstLoopingScroller))
+#define GST_LOOPINGSCROLLER_GET_CLASS(obj)				\
+  (G_TYPE_INSTANCE_GET_CLASS						\
+   ((obj), GST_TYPE_LOOPINGSCROLLER, GstLoopingScrollerClass))
+#define GST_IS_LOOPINGSCROLLER(obj)					\
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_LOOPINGSCROLLER))
+#define GST_IS_LOOPINGSCROLLER_CLASS(obj)				\
+  (G_TYPE_CHECK_CLASS_TYPE((class), GST_TYPE_LOOPINGSCROLLER))
+
+typedef struct _GstLoopingScroller      GstLoopingScroller;
+typedef struct _GstLoopingScrollerClass GstLoopingScrollerClass;
+
+struct _GstLoopingScroller {
+  GstScroller scroller;
+};
+
+struct _GstLoopingScrollerClass {
+  GstScrollerClass parent_class;
+};
+
+GType gst_loopingscroller_get_type(void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif
+
+/*
+ * Local variables:
+ * mode: c
+ * file-style: k&r
+ * c-basic-offset: 2
+ * arch-tag: f0ddca21-f0d7-4f4e-a8f9-3f5cdff69bd1
+ * End:
+ */
--- gst/scroller/gstscroller.c	1970-01-01 01:00:00.000000000 +0100
+++ gst/scroller/gstscroller.c	2005-02-09 14:45:18.385195338 +0100
@@ -0,0 +1,307 @@
+/* GStreamer
+ * Copyright (C) 2005 Gergely Nagy <gergely.nagy@neteyes.hu>
+ *
+ * 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 "gstscroller.h"
+
+GST_DEBUG_CATEGORY (scroller_debug);
+#define GST_CAT_DEFAULT scroller_debug
+
+enum
+{
+  ARG_0,
+  ARG_MAX_X,
+  ARG_MAX_Y,
+  ARG_MIN_X,
+  ARG_MIN_Y,
+  ARG_STEP,
+  ARG_SPEED,
+};
+
+static GstStaticPadTemplate gst_scroller_src_template =
+    GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("video/x-raw-yuv; video/x-raw-rgb")
+    );
+
+static GstStaticPadTemplate gst_scroller_sink_template =
+    GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("video/x-raw-yuv; video/x-raw-rgb")
+    );
+
+static GstElementClass *parent_class = NULL;
+
+static void gst_scroller_base_init (gpointer g_class);
+
+GType
+gst_scroller_get_type (void)
+{
+  static GType scroller_type = 0;
+
+  if (!scroller_type) {
+    static const GTypeInfo scroller_info = {
+      sizeof (GstScrollerClass),
+      gst_scroller_base_init,
+      NULL,
+      (GClassInitFunc) gst_scroller_class_init,
+      NULL,
+      NULL,
+      sizeof (GstScroller),
+      0,
+      (GInstanceInitFunc) gst_scroller_init,
+    };
+
+    scroller_type = g_type_register_static (GST_TYPE_ELEMENT,
+					    "GstScroller", &scroller_info, 0);
+  }
+
+  return scroller_type;
+}
+
+void
+gst_scroller_class_add_pad_templates (gpointer g_class)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_add_pad_template
+    (element_class, gst_static_pad_template_get (&gst_scroller_sink_template));
+  gst_element_class_add_pad_template
+    (element_class, gst_static_pad_template_get (&gst_scroller_src_template));
+}
+
+static void
+gst_scroller_base_init (gpointer g_class)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+  static GstElementDetails scroller_details = {
+    "Video scroller",
+    "Filter/Effect/Video",
+    "Scrolls video images",
+    "Gergely Nagy <gergely.nagy@neteyes.hu>"
+  };
+
+  gst_element_class_set_details (element_class, &scroller_details);
+}
+
+void
+gst_scroller_class_init (GstScrollerClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+  GstElementClass *element_class = GST_ELEMENT_CLASS (class);
+  GstScrollerClass *scroller_class = GST_SCROLLER_CLASS (class);
+
+  parent_class = g_type_class_peek_parent (class);
+
+  g_object_class_install_property
+    (object_class, ARG_MAX_X, g_param_spec_int
+     ("max-x", "Maximum X position", "Maximum X position", G_MININT32,
+      G_MAXINT32, 0, G_PARAM_READWRITE));
+  g_object_class_install_property
+    (object_class, ARG_MAX_Y, g_param_spec_int
+     ("max-y", "Maximum Y position", "Maximum Y position", G_MININT32,
+      G_MAXINT32, 0, G_PARAM_READWRITE));
+  g_object_class_install_property
+    (object_class, ARG_MIN_X, g_param_spec_int
+     ("min-x", "Minimum X position", "Minimum X position", G_MININT32,
+      G_MAXINT32, 0, G_PARAM_READWRITE));
+  g_object_class_install_property
+    (object_class, ARG_MIN_Y, g_param_spec_int
+     ("min-y", "Minimum Y position", "Minimum Y position", G_MININT32,
+      G_MAXINT32, 0, G_PARAM_READWRITE));
+  g_object_class_install_property
+    (object_class, ARG_STEP, g_param_spec_uint
+     ("step", "Scrolling step", "Scrolling step", 0, G_MAXUINT, 1,
+      G_PARAM_READWRITE));
+  g_object_class_install_property
+    (object_class, ARG_SPEED, g_param_spec_uint
+     ("speed", "Stepping speed", "Stepping speed", 0, G_MAXUINT, 1,
+      G_PARAM_READWRITE));
+
+  object_class->set_property = gst_scroller_set_property;
+  object_class->get_property = gst_scroller_get_property;
+
+  scroller_class->position = NULL;
+}
+
+void
+gst_scroller_init (GstScroller *scroller)
+{
+  scroller->sinkpad =
+      gst_pad_new_from_template (gst_static_pad_template_get
+      (&gst_scroller_sink_template), "sink");
+  gst_element_add_pad (GST_ELEMENT (scroller), scroller->sinkpad);
+  gst_pad_set_chain_function (scroller->sinkpad, gst_scroller_chain);
+  gst_pad_set_link_function (scroller->sinkpad, gst_pad_proxy_pad_link);
+  gst_pad_set_getcaps_function (scroller->sinkpad, gst_pad_proxy_getcaps);
+
+  scroller->srcpad =
+      gst_pad_new_from_template (gst_static_pad_template_get
+      (&gst_scroller_src_template), "src");
+  gst_element_add_pad (GST_ELEMENT (scroller), scroller->srcpad);
+  gst_pad_set_link_function (scroller->srcpad, gst_pad_proxy_link);
+  gst_pad_set_getcaps_function (scroller->srcpad, gst_pad_proxy_getcaps);
+
+  scroller->current_pos.x = scroller->current_pos.y = 0;
+  scroller->current_direction.x = scroller->current_direction.y = 0;
+  scroller->min_pos.x = scroller->min_pos.y = 0;
+  scroller->max_pos.x = scroller->max_pos.y = 0;
+  scroller->initialised = FALSE;
+  scroller->step = 1;
+  scroller->speed = 1;
+  scroller->iteration = 0;
+}
+
+void
+gst_scroller_chain (GstPad *pad, GstData *data)
+{
+  GstScroller *scroller = GST_SCROLLER (gst_pad_get_parent (pad));
+  GstBuffer *buf;
+  GObject *peer =
+    G_OBJECT (gst_pad_get_parent (gst_pad_get_peer (scroller->srcpad)));
+  GValue v;
+  GstScrollerPositionFunc position;
+
+  position =
+    GST_SCROLLER_CLASS (G_OBJECT_GET_CLASS (scroller))->position;
+
+  memset (&v, 0, sizeof (GValue));
+  g_value_init (&v, G_TYPE_INT);
+
+  scroller->iteration++;
+
+  if (!scroller->initialised) {
+    g_object_get_property (peer, "xpos", &v);
+    scroller->current_pos.x = g_value_get_int (&v);
+    g_object_set_property (peer, "xpos", &v);
+
+    g_object_get_property (peer, "ypos", &v);
+    scroller->current_pos.y = g_value_get_int (&v);
+    g_object_set_property (peer, "ypos", &v);
+
+    gst_pad_push (scroller->srcpad, data);
+
+    if (position)
+      position (scroller);
+
+    scroller->initialised = TRUE;
+
+    return;
+  }
+
+  if (position)
+    position (scroller);
+
+  g_value_set_int (&v, scroller->current_pos.x);
+  g_object_set_property (peer, "xpos", &v);
+  g_value_set_int (&v, scroller->current_pos.y);
+  g_object_set_property (peer, "ypos", &v);
+
+  gst_pad_push (scroller->srcpad, data);
+}
+
+void
+gst_scroller_set_property (GObject *object,
+			   guint prop_id, const GValue *value,
+			   GParamSpec *pspec)
+{
+  GstScroller *scroller = GST_SCROLLER (object);
+
+  switch (prop_id) {
+  case ARG_MAX_X:
+    scroller->max_pos.x = g_value_get_int (value);
+    break;
+  case ARG_MAX_Y:
+    scroller->max_pos.y = g_value_get_int (value);
+    break;
+  case ARG_MIN_X:
+    scroller->min_pos.x = g_value_get_int (value);
+    break;
+  case ARG_MIN_Y:
+    scroller->min_pos.y = g_value_get_int (value);
+    break;
+  case ARG_STEP:
+    scroller->step = g_value_get_uint (value);
+    break;
+  case ARG_SPEED:
+    scroller->speed = g_value_get_uint (value);
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    break;
+  }
+}
+
+void
+gst_scroller_get_property (GObject *object,
+			   guint prop_id, GValue *value, GParamSpec *pspec)
+{
+  GstScroller *scroller = GST_SCROLLER (object);
+
+  switch (prop_id) {
+  case ARG_MAX_X:
+    g_value_set_int (value, scroller->max_pos.x);
+    break;
+  case ARG_MAX_Y:
+    g_value_set_int (value, scroller->max_pos.y);
+    break;
+  case ARG_MIN_X:
+    g_value_set_int (value, scroller->min_pos.x);
+    break;
+  case ARG_MIN_Y:
+    g_value_set_int (value, scroller->min_pos.y);
+    break;
+  case ARG_STEP:
+    g_value_set_uint (value, scroller->step);
+    break;
+  case ARG_SPEED:
+    g_value_set_uint (value, scroller->speed);
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    break;
+  }
+}
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+  GST_DEBUG_CATEGORY_INIT (scroller_debug, "scroller", 0, "Video scroller");
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+		   GST_VERSION_MINOR,
+		   "gstscroller",
+		   "Video scroller parent class",
+		   plugin_init, VERSION, GST_LICENSE, GST_PACKAGE, GST_ORIGIN)
+
+/*
+ * Local variables:
+ * mode: c
+ * file-style: k&r
+ * c-basic-offset: 2
+ * arch-tag: abad9c51-b131-4ddd-bb05-ad0a41c1cc85
+ * End:
+ */
--- gst/scroller/gstscroller.h	1970-01-01 01:00:00.000000000 +0100
+++ gst/scroller/gstscroller.h	2005-02-09 14:45:18.385195338 +0100
@@ -0,0 +1,95 @@
+/* GStreamer
+ * Copyright (C) 2005 Gergely Nagy <gergely.nagy@neteyes.hu>
+ *
+ * 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_SCROLLER_H__
+#define __GST_SCROLLER_H__ 1
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_SCROLLER		(gst_scroller_get_type())
+#define GST_SCROLLER(obj)						\
+    (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_SCROLLER, GstScroller))
+#define GST_SCROLLER_CLASS(class)					\
+    (G_TYPE_CHECK_CLASS_CAST((class), GST_TYPE_SCROLLER, GstScrollerClass))
+#define GST_SCROLLER_GET_CLASS(obj)					\
+    (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_SCROLLER, GstScrollerClass))
+#define GST_IS_SCROLLER(obj)					\
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_SCROLLER))
+#define GST_IS_SCROLLER_CLASS(obj)			\
+    (G_TYPE_CHECK_CLASS_TYPE((class), GST_TYPE_SCROLLER))
+
+typedef struct _GstScroller      GstScroller;
+typedef struct _GstScrollerClass GstScrollerClass;
+
+typedef void (*GstScrollerPositionFunc) (GstScroller *scroller);
+
+typedef struct _GstScrollerPosition GstScrollerPosition;
+struct _GstScrollerPosition {
+  gint x, y;
+};
+
+struct _GstScroller {
+  GstElement element;
+
+  /* pads */
+  GstPad *srcpad, *sinkpad;
+
+  /* properties */
+  GstScrollerPosition min_pos, max_pos;
+  guint step, speed;
+
+  /* internal */
+  GstScrollerPosition current_pos, current_direction;
+
+  gboolean initialised;
+  guint iteration;
+};
+
+struct _GstScrollerClass {
+  GstElementClass parent_class;
+
+  GstScrollerPositionFunc position;
+};
+
+GType gst_scroller_get_type(void) G_GNUC_CONST;
+void gst_scroller_chain (GstPad *pad, GstData *data);
+void gst_scroller_class_add_pad_templates (gpointer g_class);
+void gst_scroller_class_init (GstScrollerClass *g_class);
+void gst_scroller_init (GstScroller *scroller);
+
+void gst_scroller_set_property (GObject *object,
+				guint prop_id, const GValue *value,
+				GParamSpec *pspec);
+void gst_scroller_get_property (GObject *object, guint prop_id, GValue *value,
+				GParamSpec *pspec);
+
+G_END_DECLS
+
+#endif
+
+/*
+ * Local variables:
+ * mode: c
+ * file-style: k&r
+ * c-basic-offset: 2
+ * arch-tag: c903072b-2cdb-4f76-adf5-3dbaa67fda9e
+ * End:
+ */
--- gst/scroller/Makefile.am	1970-01-01 01:00:00.000000000 +0100
+++ gst/scroller/Makefile.am	2005-02-09 14:45:18.384195495 +0100
@@ -0,0 +1,20 @@
+plugin_LTLIBRARIES			= libgstscroller.la \
+					libgstbouncingscroller.la \
+					libgstloopingscroller.la
+
+libgstscroller_la_SOURCES		= gstscroller.c
+libgstscroller_la_CFLAGS		= ${GST_CFLAGS}
+libgstscroller_la_LIBADD		= ${GST_LIBS}
+libgstscroller_la_LDFLAGS		= ${GST_PLUGIN_LDFLAGS}
+
+libgstbouncingscroller_la_SOURCES	= gstbouncingscroller.c
+libgstbouncingscroller_la_CFLAGS	= ${GST_CFLAGS}
+libgstbouncingscroller_la_LIBADD	= ${GST_LIBS}
+libgstbouncingscroller_la_LDFLAGS	= ${GST_PLUGIN_LDFLAGS}
+
+libgstloopingscroller_la_SOURCES	= gstloopingscroller.c
+libgstloopingscroller_la_CFLAGS		= ${GST_CFLAGS}
+libgstloopingscroller_la_LIBADD		= ${GST_LIBS}
+libgstloopingscroller_la_LDFLAGS	= ${GST_PLUGIN_LDFLAGS}
+
+noinst_HEADERS		= gstscroller.h
