diff -u -p -r1.95 gstgnomevfssrc.c
--- ext/gnomevfs/gstgnomevfssrc.c	10 Oct 2006 12:49:01 -0000	1.95
+++ ext/gnomevfs/gstgnomevfssrc.c	22 Oct 2006 06:32:25 -0000
@@ -147,6 +147,9 @@ static void gst_gnome_vfs_src_set_proper
 static void gst_gnome_vfs_src_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
 
+static GstStateChangeReturn gst_gnome_vfs_src_change_state (GstElement * element,
+    GstStateChange transition);
+
 static gboolean gst_gnome_vfs_src_stop (GstBaseSrc * src);
 static gboolean gst_gnome_vfs_src_start (GstBaseSrc * src);
 static gboolean gst_gnome_vfs_src_is_seekable (GstBaseSrc * src);
@@ -254,6 +257,7 @@ gst_gnome_vfs_src_class_init (GstGnomeVF
           "iradio-title",
           "Name of currently playing song", NULL, G_PARAM_READABLE));
 
+  gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_change_state);
   gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_start);
   gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_stop);
   gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_get_size);
@@ -896,3 +900,60 @@ gst_gnome_vfs_src_stop (GstBaseSrc * bas
 
   return TRUE;
 }
+
+
+typedef struct {
+  GstElement *element;
+  GstStateChange transition;
+} StateTransitionAsyncData;
+
+static gpointer
+_async_state_transition (gpointer userdata)
+{
+  StateTransitionAsyncData *data;
+  GstStateChangeReturn result;
+
+  data = (StateTransitionAsyncData *)userdata;
+  result = GST_ELEMENT_CLASS (parent_class)->
+             change_state (data->element, data->transition);
+
+  if (result == GST_STATE_CHANGE_ASYNC) {
+    /* wait for real result */
+    result = gst_element_get_state (data->element,
+                                    NULL, NULL,
+                                    GST_CLOCK_TIME_NONE);
+  }
+
+  gst_element_continue_state (data->element, result);
+
+  gst_object_unref (data->element);
+  g_free (data);
+}
+
+static GstStateChangeReturn
+gst_gnome_vfs_src_change_state (GstElement * element, GstStateChange transition)
+{
+  GError *error = NULL;
+
+  if (transition == GST_STATE_CHANGE_READY_TO_PAUSED ||
+      transition == GST_STATE_CHANGE_PAUSED_TO_READY) {
+    /* do start and stop asynchronously */
+    StateTransitionAsyncData *data;
+
+    data = g_new0 (StateTransitionAsyncData, 1);
+    data->element = gst_object_ref (element);
+    data->transition = transition;
+    g_thread_create (_async_state_transition, data, FALSE, &error);
+
+    if (error == NULL) {
+      return GST_STATE_CHANGE_ASYNC;
+    } else {
+      GST_LOG_OBJECT (element, "error creating thread: %s", error->message);
+      g_error_free (error);
+      g_free (data);
+      return GST_STATE_CHANGE_FAILURE;
+    }
+  } else {
+    return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+  }
+}
