diff --git a/gst/playback/gstplaysink.c b/gst/playback/gstplaysink.c
index cc90fae..bdea9ef 100644
--- a/gst/playback/gstplaysink.c
+++ b/gst/playback/gstplaysink.c
@@ -198,6 +198,8 @@ static gboolean gst_play_sink_send_event (GstElement * element,
 static GstStateChangeReturn gst_play_sink_change_state (GstElement * element,
     GstStateChange transition);
 
+static void gst_play_sink_handle_message (GstBin * bin, GstMessage * message);
+
 /* static guint gst_play_sink_signals[LAST_SIGNAL] = { 0 }; */
 
 static const GstElementDetails gst_play_sink_details =
@@ -228,6 +230,9 @@ gst_play_sink_class_init (GstPlaySinkClass * klass)
       GST_DEBUG_FUNCPTR (gst_play_sink_change_state);
   gstelement_klass->send_event = GST_DEBUG_FUNCPTR (gst_play_sink_send_event);
 
+  gstbin_klass->handle_message =
+      GST_DEBUG_FUNCPTR (gst_play_sink_handle_message);
+
   GST_DEBUG_CATEGORY_INIT (gst_play_sink_debug, "playsink", 0, "play bin");
 }
 
@@ -1775,8 +1780,8 @@ gst_play_sink_reconfigure (GstPlaySink * playsink)
           playsink->audio_tee_vissrc = NULL;
         }
         srcpad =
-            gst_element_get_static_pad (GST_ELEMENT_CAST (playsink->vischain->
-                chain.bin), "src");
+            gst_element_get_static_pad (GST_ELEMENT_CAST (playsink->
+                vischain->chain.bin), "src");
         gst_pad_unlink (srcpad, playsink->videochain->sinkpad);
       }
       add_chain (GST_PLAY_CHAIN (playsink->videochain), FALSE);
@@ -1941,8 +1946,8 @@ gst_play_sink_reconfigure (GstPlaySink * playsink)
     if (playsink->vischain) {
       GST_DEBUG_OBJECT (playsink, "setting up vis chain");
       srcpad =
-          gst_element_get_static_pad (GST_ELEMENT_CAST (playsink->vischain->
-              chain.bin), "src");
+          gst_element_get_static_pad (GST_ELEMENT_CAST (playsink->
+              vischain->chain.bin), "src");
       add_chain (GST_PLAY_CHAIN (playsink->vischain), TRUE);
       activate_chain (GST_PLAY_CHAIN (playsink->vischain), TRUE);
       if (playsink->audio_tee_vissrc == NULL) {
@@ -2256,6 +2261,51 @@ gst_play_sink_release_pad (GstPlaySink * playsink, GstPad * pad)
   }
 }
 
+static void
+gst_play_sink_handle_message (GstBin * bin, GstMessage * message)
+{
+  GstPlaySink *playsink;
+
+  playsink = GST_PLAY_SINK_CAST (bin);
+
+  switch (GST_MESSAGE_TYPE (message)) {
+    case GST_MESSAGE_STEP_DONE:
+    {
+      GstFormat format;
+      guint64 amount;
+      gdouble rate;
+      gboolean flush, intermediate, res;
+      guint64 duration;
+
+      GST_INFO_OBJECT (playsink, "Handling step-done message");
+      gst_message_parse_step_done (message, &format, &amount, &rate, &flush,
+          &intermediate, &duration);
+
+      if (format == GST_FORMAT_BUFFERS) {
+        /* for the buffer format, we align the other streams */
+        if (playsink->audiochain) {
+          GstEvent *event;
+
+          event =
+              gst_event_new_step (GST_FORMAT_TIME, duration, rate, flush,
+              intermediate);
+
+          if (!(res =
+                  gst_element_send_event (playsink->audiochain->chain.bin,
+                      event))) {
+            GST_DEBUG_OBJECT (playsink, "Event failed when sent to audio sink");
+          }
+        }
+      }
+      GST_BIN_CLASS (gst_play_sink_parent_class)->handle_message (bin, message);
+      break;
+    }
+    default:
+      GST_BIN_CLASS (gst_play_sink_parent_class)->handle_message (bin, message);
+      break;
+  }
+}
+
 /* Send an event to our sinks until one of them works; don't then send to the
  * remaining sinks (unlike GstBin)
  */
@@ -2293,12 +2343,36 @@ gst_play_sink_send_event (GstElement * element, GstEvent * event)
 {
   gboolean res = FALSE;
   GstEventType event_type = GST_EVENT_TYPE (event);
+  GstPlaySink *playsink;
+
+  playsink = GST_PLAY_SINK_CAST (element);
 
   switch (event_type) {
     case GST_EVENT_SEEK:
-      GST_DEBUG_OBJECT (element, "Sending seek event to a sink");
-      res = gst_play_sink_send_event_to_sink (GST_PLAY_SINK (element), event);
+      GST_DEBUG_OBJECT (element, "Sending event to a sink");
+      res = gst_play_sink_send_event_to_sink (playsink, event);
+      break;
+    case GST_EVENT_STEP:
+    {
+      GstFormat format;
+      guint64 amount;
+      gdouble rate;
+      gboolean flush, intermediate;
+
+      gst_event_parse_step (event, &format, &amount, &rate, &flush,
+          &intermediate);
+
+      if (format == GST_FORMAT_BUFFERS) {
+        /* for buffers, we will try to step video frames, for other formats we
+         * send the step to all sinks */
+        res = gst_play_sink_send_event_to_sink (playsink, event);
+      } else {
+        res =
+            GST_ELEMENT_CLASS (gst_play_sink_parent_class)->send_event (element,
+            event);
+      }
       break;
+    }
     default:
       res =
           GST_ELEMENT_CLASS (gst_play_sink_parent_class)->send_event (element,
diff --git a/tests/examples/seek/seek.c b/tests/examples/seek/seek.c
index 861236b..a092ccc 100644
--- a/tests/examples/seek/seek.c
+++ b/tests/examples/seek/seek.c
@@ -109,7 +109,10 @@ static GtkWidget *vis_checkbox, *video_checkbox, *audio_checkbox;
 static GtkWidget *text_checkbox, *mute_checkbox, *volume_spinbutton;
 static GtkWidget *skip_checkbox, *video_window;
 
-GList *paths = NULL, *l = NULL;
+static GtkWidget *format_combo, *step_amount_spinbutton, *step_rate_spinbutton;
+static GtkWidget *step_flush_checkbox, *step_button;
+
+static GList *paths = NULL, *l = NULL;
 
 /* we keep an array of the visualisation entries so that we can easily switch
  * with the combo box index. */
@@ -1209,6 +1212,7 @@ update_scale (gpointer data)
     }
     query_rates ();
   }
+
   if (position >= duration)
     duration = position;
 
@@ -1978,6 +1982,43 @@ shot_cb (GtkButton * button, gpointer data)
   }
 }
 
+/* called when the Step button is pressed */
+static void
+step_cb (GtkButton * button, gpointer data)
+{
+  GstEvent *event;
+  GstFormat format;
+  guint64 amount;
+  gdouble rate;
+  gboolean flush, res;
+  gint active;
+
+  active = gtk_combo_box_get_active (GTK_COMBO_BOX (format_combo));
+  amount =
+      gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON
+      (step_amount_spinbutton));
+  rate = gtk_spin_button_get_value (GTK_SPIN_BUTTON (step_rate_spinbutton));
+  flush =
+      gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (step_flush_checkbox));
+
+  switch (active) {
+    case 0:
+      format = GST_FORMAT_BUFFERS;
+      break;
+    case 1:
+      format = GST_FORMAT_TIME;
+      amount *= GST_MSECOND;
+      break;
+    default:
+      format = GST_FORMAT_UNDEFINED;
+      break;
+  }
+
+  event = gst_event_new_step (format, amount, rate, flush, FALSE);
+
+  res = send_event (event);
+}
+
 static void
 message_received (GstBus * bus, GstMessage * message, GstPipeline * pipeline)
 {
@@ -2212,6 +2253,12 @@ msg_eos (GstBus * bus, GstMessage * message, GstPipeline * data)
 }
 
 static void
+msg_step_done (GstBus * bus, GstMessage * message, GstPipeline * data)
+{
+  message_received (bus, message, data);
+}
+
+static void
 connect_bus_signals (GstElement * pipeline)
 {
   GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
@@ -2248,6 +2295,8 @@ connect_bus_signals (GstElement * pipeline)
       pipeline);
   g_signal_connect (bus, "message::buffering", (GCallback) msg_buffering,
       pipeline);
+  g_signal_connect (bus, "message::step-done", (GCallback) msg_step_done,
+      pipeline);
 
   gst_object_unref (bus);
 }
@@ -2310,7 +2359,7 @@ int
 main (int argc, char **argv)
 {
   GtkWidget *window, *hbox, *vbox, *panel, *expander, *pb2vbox, *boxes,
-      *flagtable, *boxes2;
+      *flagtable, *boxes2, *step;
   GtkWidget *play_button, *pause_button, *stop_button, *shot_button;
   GtkWidget *accurate_checkbox, *key_checkbox, *loop_checkbox, *flush_checkbox;
   GtkWidget *scrub_checkbox, *play_scrub_checkbox, *rate_spinbutton;
@@ -2429,6 +2478,45 @@ main (int argc, char **argv)
 
   gtk_spin_button_set_value (GTK_SPIN_BUTTON (rate_spinbutton), rate);
 
+  /* step expander */
+  {
+    GtkWidget *hbox;
+
+    step = gtk_expander_new ("step options");
+    hbox = gtk_hbox_new (FALSE, 0);
+
+    format_combo = gtk_combo_box_new_text ();
+    gtk_combo_box_append_text (GTK_COMBO_BOX (format_combo), "frames");
+    gtk_combo_box_append_text (GTK_COMBO_BOX (format_combo), "time (ms)");
+    gtk_combo_box_set_active (GTK_COMBO_BOX (format_combo), 0);
+    gtk_box_pack_start (GTK_BOX (hbox), format_combo, FALSE, FALSE, 2);
+
+    step_amount_spinbutton = gtk_spin_button_new_with_range (1, 1000, 1);
+    gtk_spin_button_set_digits (GTK_SPIN_BUTTON (step_amount_spinbutton), 0);
+    gtk_spin_button_set_value (GTK_SPIN_BUTTON (step_amount_spinbutton), 1.0);
+    gtk_box_pack_start (GTK_BOX (hbox), step_amount_spinbutton, FALSE, FALSE,
+        2);
+
+    step_rate_spinbutton = gtk_spin_button_new_with_range (0.0, 100, 0.1);
+    gtk_spin_button_set_digits (GTK_SPIN_BUTTON (step_rate_spinbutton), 3);
+    gtk_spin_button_set_value (GTK_SPIN_BUTTON (step_rate_spinbutton), 1.0);
+    gtk_box_pack_start (GTK_BOX (hbox), step_rate_spinbutton, FALSE, FALSE, 2);
+
+    step_flush_checkbox = gtk_check_button_new_with_label ("Flush");
+    gtk_box_pack_start (GTK_BOX (hbox), step_flush_checkbox, FALSE, FALSE, 2);
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (step_flush_checkbox),
+        TRUE);
+
+    step_button = gtk_button_new_from_stock (GTK_STOCK_MEDIA_FORWARD);
+    gtk_button_set_label (GTK_BUTTON (step_button), "Step");
+    gtk_box_pack_start (GTK_BOX (hbox), step_button, FALSE, FALSE, 2);
+
+    g_signal_connect (G_OBJECT (step_button), "clicked", G_CALLBACK (step_cb),
+        pipeline);
+
+    gtk_container_add (GTK_CONTAINER (step), hbox);
+  }
+
   /* seek bar */
   adjustment =
       GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.00, 100.0, 0.1, 1.0, 1.0));
@@ -2551,6 +2639,7 @@ main (int argc, char **argv)
     gtk_container_add (GTK_CONTAINER (expander), pb2vbox);
     gtk_box_pack_start (GTK_BOX (vbox), expander, FALSE, FALSE, 2);
   }
+  gtk_box_pack_start (GTK_BOX (vbox), step, FALSE, FALSE, 2);
   gtk_box_pack_start (GTK_BOX (vbox), hscale, FALSE, FALSE, 2);
   gtk_box_pack_start (GTK_BOX (vbox), statusbar, FALSE, FALSE, 2);
 
