diff -up gst-plugins-bad-0.10.5/ext/libmms/gstmms.c.seek gst-plugins-bad-0.10.5/ext/libmms/gstmms.c
--- gst-plugins-bad-0.10.5/ext/libmms/gstmms.c.seek	2006-12-16 16:14:20.000000000 +0100
+++ gst-plugins-bad-0.10.5/ext/libmms/gstmms.c	2007-08-24 14:32:34.000000000 +0200
@@ -62,7 +62,14 @@ static gboolean gst_mms_src_query (GstPa
 
 static gboolean gst_mms_start (GstBaseSrc * bsrc);
 static gboolean gst_mms_stop (GstBaseSrc * bsrc);
-static GstFlowReturn gst_mms_create (GstPushSrc * psrc, GstBuffer ** buf);
+static gboolean gst_mms_unlock (GstBaseSrc * bsrc);
+static gboolean gst_mms_unlock_stop (GstBaseSrc * bsrc);
+static gboolean gst_mms_is_seekable (GstBaseSrc *src);
+static gboolean gst_mms_get_size (GstBaseSrc *src, guint64 *size);
+static gboolean gst_mms_do_seek (GstBaseSrc *src, GstSegment *segment);
+
+static GstFlowReturn gst_mms_create (GstBaseSrc * psrc, guint64 offset,
+  guint size, GstBuffer ** buf);
 
 static void
 gst_mms_urihandler_init (GType mms_type)
@@ -77,7 +84,7 @@ gst_mms_urihandler_init (GType mms_type)
       &urihandler_info);
 }
 
-GST_BOILERPLATE_FULL (GstMMS, gst_mms, GstPushSrc, GST_TYPE_PUSH_SRC,
+GST_BOILERPLATE_FULL (GstMMS, gst_mms, GstBaseSrc, GST_TYPE_BASE_SRC,
     gst_mms_urihandler_init);
 
 static void
@@ -98,11 +105,9 @@ gst_mms_class_init (GstMMSClass * klass)
 {
   GObjectClass *gobject_class;
   GstBaseSrcClass *gstbasesrc_class;
-  GstPushSrcClass *gstpushsrc_class;
 
   gobject_class = (GObjectClass *) klass;
   gstbasesrc_class = (GstBaseSrcClass *) klass;
-  gstpushsrc_class = (GstPushSrcClass *) klass;
 
   gobject_class->set_property = gst_mms_set_property;
   gobject_class->get_property = gst_mms_get_property;
@@ -115,8 +120,12 @@ gst_mms_class_init (GstMMSClass * klass)
 
   gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_mms_start);
   gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_mms_stop);
-
-  gstpushsrc_class->create = GST_DEBUG_FUNCPTR (gst_mms_create);
+  gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_mms_unlock);
+  gstbasesrc_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_mms_unlock_stop);
+  gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (gst_mms_is_seekable);
+  gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_mms_get_size);
+  gstbasesrc_class->do_seek = GST_DEBUG_FUNCPTR (gst_mms_do_seek);
+  gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_mms_create);
 
 }
 
@@ -136,6 +145,9 @@ gst_mms_init (GstMMS * mmssrc, GstMMSCla
   mmssrc->uri_name = NULL;
   mmssrc->connection = NULL;
   mmssrc->connection_h = NULL;
+  g_static_mutex_init (&mmssrc->stop_lock);
+  mmssrc->stop_count = 0;
+  
   GST_BASE_SRC (mmssrc)->blocksize = 2048;
 }
 
@@ -164,6 +176,7 @@ gst_mms_get_query_types (GstPad * pad)
   static const GstQueryType types[] = {
     GST_QUERY_POSITION,
     GST_QUERY_DURATION,
+    GST_QUERY_CONVERT,
     0
   };
 
@@ -195,17 +208,52 @@ gst_mms_src_query (GstPad * pad, GstQuer
       break;
     case GST_QUERY_DURATION:
       gst_query_parse_duration (query, &format, &value);
-      if (format != GST_FORMAT_BYTES) {
+      switch (format) {
+        case GST_FORMAT_BYTES:
+          if (mmssrc->connection) {
+            value = (gint64) mms_get_length (mmssrc->connection);
+          } else {
+            value = (gint64) mmsh_get_length (mmssrc->connection_h);
+          }
+          gst_query_set_duration (query, format, value);
+          break;
+        case GST_FORMAT_TIME:
+          if (mmssrc->connection) {
+            value = mms_get_time_length (mmssrc->connection) * GST_SECOND;
+            gst_query_set_duration (query, format, value);
+            break;
+          }
+        default:
+          res = FALSE;
+      }
+      break;
+    case GST_QUERY_CONVERT:
+    {
+      GstFormat src_fmt, dest_fmt;
+      gint64 src_val, dest_val;
+
+      gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
+      if (src_fmt != GST_FORMAT_TIME || dest_fmt != GST_FORMAT_BYTES ||
+            !mmssrc->connection) {
         res = FALSE;
         break;
       }
-      if (mmssrc->connection) {
-        value = (gint64) mms_get_length (mmssrc->connection);
-      } else {
-        value = (gint64) mmsh_get_length (mmssrc->connection_h);
+      /* In order to get the offset into the stream to seek to in bytes, we
+         need to do a time_seek, this may seem expensive, but normally this is
+         not an issue, as normally we are queried for a conversion to determine
+         the offset for the next pull when seeking. So the seek needs to be
+         done, one way or the other anyway, and thus this is fine. */
+      if (!mms_time_seek(NULL, mmssrc->connection,
+            (double)src_val/GST_SECOND)) {
+        res = FALSE;
+        break;
       }
-      gst_query_set_duration (query, format, value);
+      dest_val = mms_get_current_pos (mmssrc->connection);
+      gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
+      GST_LOG_OBJECT (pad, "sought to %f sec due to convert query, offset after seek: %lld\n",
+        (double)src_val/GST_SECOND, dest_val);
       break;
+    }
     default:
       res = FALSE;
       break;
@@ -216,24 +264,78 @@ gst_mms_src_query (GstPad * pad, GstQuer
 
 }
 
+
+static gboolean
+gst_mms_unlock (GstBaseSrc * src)
+{
+  GstMMS *mmssrc = GST_MMS (src);
+
+  GST_LOG_OBJECT (mmssrc, "sending unlock command");
+
+  g_static_mutex_lock(&mmssrc->stop_lock);
+  mmssrc->stop_count++;
+  g_static_mutex_unlock(&mmssrc->stop_lock);
+
+  return TRUE;
+}
+ 
+static gboolean
+gst_mms_unlock_stop (GstBaseSrc * src)
+{
+  GstMMS *mmssrc = GST_MMS (src);
+
+  GST_LOG_OBJECT (mmssrc, "clearing unlock queue");
+
+  g_static_mutex_lock(&mmssrc->stop_lock);
+  mmssrc->stop_count = 0;
+  g_static_mutex_unlock(&mmssrc->stop_lock);
+     
+  return TRUE;
+}
+
+
 /* get function
  * this function generates new data when needed
  */
 
 
 static GstFlowReturn
-gst_mms_create (GstPushSrc * psrc, GstBuffer ** buf)
+gst_mms_create (GstBaseSrc * psrc, guint64 offset, guint size,
+  GstBuffer ** buf)
 {
   GstMMS *mmssrc;
   guint8 *data;
   guint blocksize;
   gint result;
+  gboolean stopped = FALSE;
 
   mmssrc = GST_MMS (psrc);
 
-  GST_OBJECT_LOCK (mmssrc);
-  blocksize = GST_BASE_SRC (mmssrc)->blocksize;
-  GST_OBJECT_UNLOCK (mmssrc);
+  if (mmssrc->connection) {
+    guint64 offset_before_seek = mms_get_current_pos (mmssrc->connection);
+    if (offset_before_seek != offset) {
+      /* Once we've read or seeked to the last packet of the stream any further
+         seeks will fail, this is signaled by libmms by returning the last
+         position. The only thing we can do then is reopen the connection */
+      if (mms_seek(NULL, mmssrc->connection, offset, SEEK_SET) ==
+            offset_before_seek) {
+        GST_DEBUG_OBJECT (mmssrc, "warning resetting connection (seek failed)");
+        mms_close(mmssrc->connection);
+        mmssrc->connection = mms_connect (NULL, NULL, mmssrc->uri_name,
+            128 * 1024);
+        if (!mmssrc->connection) {
+          GST_ERROR_OBJECT (mmssrc, "error reopening connection");
+          return GST_FLOW_ERROR;
+        }
+        mms_seek(NULL, mmssrc->connection, offset, SEEK_SET);
+      }
+    }
+    blocksize = size;
+  } else { 
+    GST_OBJECT_LOCK (mmssrc);
+    blocksize = GST_BASE_SRC (mmssrc)->blocksize;
+    GST_OBJECT_UNLOCK (mmssrc);
+  }
 
   *buf = gst_buffer_new_and_alloc (blocksize);
 
@@ -246,6 +348,17 @@ gst_mms_create (GstPushSrc * psrc, GstBu
     result = mmsh_read (NULL, mmssrc->connection_h, (char *) data, blocksize);
   }
 
+  /* Stopped / unblocked? */
+  g_static_mutex_lock(&mmssrc->stop_lock);
+  if (mmssrc->stop_count) {
+    stopped = TRUE;
+    mmssrc->stop_count--;
+  }
+  g_static_mutex_unlock(&mmssrc->stop_lock);
+
+  if (stopped)
+    goto stopped;
+
   /* EOS? */
   if (result == 0)
     goto eos;
@@ -273,6 +386,63 @@ eos:
     *buf = NULL;
     return GST_FLOW_UNEXPECTED;
   }
+stopped:
+  {
+    GST_DEBUG_OBJECT (mmssrc, "Stopped");
+    gst_buffer_unref (*buf);
+    *buf = NULL;
+    return GST_FLOW_WRONG_STATE;
+  }
+}
+
+static gboolean gst_mms_is_seekable (GstBaseSrc *src)
+{
+  GstMMS *mmssrc = GST_MMS (src);
+
+  if (mmssrc->connection)
+    return TRUE;
+  else
+    return FALSE;
+}
+
+static gboolean gst_mms_get_size (GstBaseSrc *src, guint64 *size)
+{
+  GstMMS *mmssrc = GST_MMS (src);
+
+  if (mmssrc->connection) {
+    *size = mms_get_length (mmssrc->connection);
+  } else {
+    *size = mmsh_get_length (mmssrc->connection_h);
+  }
+  return TRUE;
+}
+
+/* Warning this is _completely_ untested, as asfdemux handles seeking events
+   itself and thus we never get forwarded any seek events */
+static gboolean gst_mms_do_seek (GstBaseSrc *src, GstSegment *segment)
+{
+  GstMMS *mmssrc = GST_MMS (src);
+  gboolean res = TRUE;
+  mms_off_t offset;
+
+  if (!mmssrc->connection)
+    return FALSE;
+
+  /* update our offset if the start/stop position was updated */
+  if (segment->format == GST_FORMAT_BYTES) {
+
+    GST_LOG_OBJECT (mmssrc, "seeking to: %lld bytes\n", segment->start);
+
+    offset = mms_seek(NULL, mmssrc->connection, segment->start, SEEK_SET);
+    segment->last_stop = offset;
+    segment->time = offset;
+    
+    /* TODO at support for time seeking using mms_time_seek( ... ) */
+    
+  } else
+    res = FALSE;
+
+  return res;
 }
 
 static gboolean
diff -up gst-plugins-bad-0.10.5/ext/libmms/gstmms.h.seek gst-plugins-bad-0.10.5/ext/libmms/gstmms.h
--- gst-plugins-bad-0.10.5/ext/libmms/gstmms.h.seek	2007-06-13 11:20:43.000000000 +0200
+++ gst-plugins-bad-0.10.5/ext/libmms/gstmms.h	2007-08-24 11:52:47.000000000 +0200
@@ -8,7 +8,7 @@
 #include <gst/gst.h>
 #include <libmms/mms.h>
 #include <libmms/mmsh.h>
-#include <gst/base/gstpushsrc.h>
+#include <gst/base/gstbasesrc.h>
 
 G_BEGIN_DECLS
 
@@ -29,16 +29,19 @@ typedef struct _GstMMSClass GstMMSClass;
 
 struct _GstMMS
 {
-  GstPushSrc parent;
+  GstBaseSrc parent;
 
   gchar  *uri_name;
   mms_t  *connection;
   mmsh_t *connection_h;
+  
+  GStaticMutex stop_lock;
+  gint stop_count;
 };
 
 struct _GstMMSClass 
 {
-  GstPushSrcClass parent_class;
+  GstBaseSrcClass parent_class;
 };
 
 GType gst_mms_get_type (void);
