? conf10851.file
Index: configure.ac
===================================================================
RCS file: /cvs/gnome/rhythmbox/configure.ac,v
retrieving revision 1.152
diff -u -r1.152 configure.ac
--- configure.ac	26 Aug 2005 00:48:22 -0000	1.152
+++ configure.ac	27 Aug 2005 22:36:43 -0000
@@ -123,11 +123,10 @@
 dnl And we can also ask for the right version of gstreamer
 HAVE_SOUNDSYSTEM=no
 
-GST_MAJORMINOR=0.8
-GST_REQUIRED_VERSION=0.8.2
+GST_MAJORMINOR=0.9
+GST_REQUIRED_VERSION=0.9.0
 PKG_CHECK_MODULES(SOUNDSYSTEM, \
-	gstreamer-$GST_MAJORMINOR >= $GST_REQUIRED_VERSION gstreamer-libs-$GST_MAJORMINOR >= $GST_REQUIRED_VERSION
-	gstreamer-control-$GST_MAJORMINOR >= $GST_REQUIRED_VERSION gstreamer-gconf-$GST_MAJORMINOR >= $GST_REQUIRED_VERSION,
+	gstreamer-$GST_MAJORMINOR >= $GST_REQUIRED_VERSION gstreamer-plugins-base-$GST_MAJORMINOR >= $GST_REQUIRED_VERSION,
 	HAVE_SOUNDSYSTEM=yes,HAVE_SOUNDSYSTEM=no)
 
 dnl Give error and exit if we don't have gstreamer
Index: metadata/rb-metadata-gst.c
===================================================================
RCS file: /cvs/gnome/rhythmbox/metadata/rb-metadata-gst.c,v
retrieving revision 1.43
diff -u -r1.43 rb-metadata-gst.c
--- metadata/rb-metadata-gst.c	10 Aug 2005 12:51:02 -0000	1.43
+++ metadata/rb-metadata-gst.c	27 Aug 2005 22:36:44 -0000
@@ -66,7 +66,6 @@
 	GPtrArray *supported_types;
 
 	char *type;
-	gboolean handoff;
 	gboolean eos;
 	gboolean non_audio;
 	GError *error;
@@ -99,24 +98,25 @@
 static GstElement *
 rb_add_id3_tagger (GstBin *pipeline, GstElement *element)
 {
-	GstElement *spider;
-	GstElement *tagger;
+	GstElement *spider = NULL;
+	GstElement *tagger = NULL;
+	GstElement *filter = NULL;
 	GstCaps *filtercaps = NULL;
 
-	if (!(spider = gst_element_factory_make ("spider", "spider")))
-		return NULL;
+	if (!(spider = gst_element_factory_make ("spider", "spider")) ||
+	    !(tagger = gst_element_factory_make ("id3mux", "id3mux")) ||
+	    !(filter = gst_element_factory_make ("capsfilter", NULL)) ||
+	    !(filtercaps = gst_caps_new_simple ("audio/mpeg", NULL))) {
+	    gst_object_unref (GST_OBJECT (spider));
+	    gst_object_unref (GST_OBJECT (tagger));
+	    gst_object_unref (GST_OBJECT (filter));
+	    return NULL;
+	}
 
-	if (!(tagger = gst_element_factory_make ("id3mux", "id3mux")))
-		/* FIXME: leaks spider */
-		return NULL;
-
-	gst_bin_add (GST_BIN (pipeline), spider);
-	gst_bin_add (GST_BIN (pipeline), tagger);
-	
-	gst_element_link_many (element, spider, NULL);
-	filtercaps = gst_caps_new_simple ("audio/mpeg", NULL);
-	gst_element_link_filtered (spider, tagger, filtercaps);
-	gst_caps_free (filtercaps);
+	gst_bin_add_many (GST_BIN (pipeline), spider, tagger, filter, NULL);
+	g_object_set (G_OBJECT (filter), "filter-caps", filtercaps, NULL);
+	gst_element_link_many (element, spider, filter, tagger, NULL);
+	gst_caps_unref (filtercaps);
 
 	return tagger;
 
@@ -442,12 +442,6 @@
 }
 
 static void
-rb_metadata_gst_found_tag (GObject *pipeline, GstElement *source, GstTagList *tags, RBMetaData *md)
-{
-	gst_tag_list_foreach (tags, (GstTagForeachFunc) rb_metadata_gst_load_tag, md);
-}
-
-static void
 rb_metadata_gst_typefind_cb (GstElement *typefind, guint probability, GstCaps *caps, RBMetaData *md)
 {
 	if (gst_caps_get_size (caps) > 0) {
@@ -457,22 +451,6 @@
 }
 
 static void
-rb_metadata_gst_fakesink_handoff_cb (GstElement *fakesink, GstBuffer *buf, GstPad *pad, RBMetaData *md)
-{
-	if (md->priv->handoff) {
-		/* we get lots of these with decodebin.  why? */
-		/* rb_debug ("caught recursive handoff!"); */
-		return;
-	} else if (md->priv->eos) {
-		rb_debug ("caught handoff after eos!");
-		return;
-	}
-		
-	rb_debug ("in fakesink handoff");
-	md->priv->handoff = TRUE;
-}
-
-static void
 rb_metadata_gst_new_decoded_pad_cb (GstElement *decodebin, GstPad *pad, gboolean last, RBMetaData *md)
 {
 	GstCaps *caps;
@@ -508,7 +486,7 @@
 		}
 	}
 
-	gst_caps_free (caps);
+	gst_caps_unref (caps);
 }
 
 static void
@@ -535,6 +513,102 @@
 	return elem;
 }
 
+static gboolean
+rb_metadata_bus_handler (GstBus *bus, GstMessage *message, RBMetaData *md)
+{
+  switch (GST_MESSAGE_TYPE (message)) {
+    case GST_MESSAGE_EOS:
+      rb_debug ("EOS reached");
+      md->priv->eos = TRUE;
+      break;
+    case GST_MESSAGE_ERROR:{
+      GError *gerror;
+      gchar *debug;
+
+      gst_message_parse_error (message, &gerror, &debug);
+
+      rb_debug ("caught error: %s ", gerror->message);
+      md->priv->error = g_error_new_literal (RB_METADATA_ERROR,
+      				       RB_METADATA_ERROR_GENERAL,
+      				       gerror->message);
+
+      g_error_free (gerror);
+      g_free (debug);
+      break;
+    }
+    case GST_MESSAGE_TAG: {
+      GstTagList *tags;
+
+      gst_message_parse_tag (message, &tags);
+      if (tags) {
+        gst_tag_list_foreach (tags, (GstTagForeachFunc) rb_metadata_gst_load_tag, md);
+        gst_tag_list_free (tags);
+      }
+      else {
+        const gchar *errmsg = "Could not retrieve tag list";
+        rb_debug ("caught error: %s ", errmsg);
+        md->priv->error = g_error_new_literal (RB_METADATA_ERROR,
+      				         RB_METADATA_ERROR_GENERAL,
+      				         errmsg);
+      }
+      break;
+    }
+    case GST_MESSAGE_STATE_CHANGED:
+	break;
+    default:
+	rb_debug ("message of type %d", GST_MESSAGE_TYPE (message));
+	break;
+  }
+
+  return FALSE;
+}
+
+static void 
+rb_metadata_event_loop (RBMetaData *md, GstElement *element)
+{
+	GstBus *bus;
+	gboolean done = FALSE;
+
+	bus = gst_element_get_bus (element);
+	g_return_if_fail (bus != NULL);
+
+	while (!done) {
+	    GstMessage *message;
+	    GstMessageType revent;
+
+	    revent = gst_bus_poll (bus, GST_MESSAGE_ANY, -1);
+	    if (revent == GST_MESSAGE_UNKNOWN) {
+		/* Messages ended */
+		gst_object_unref (bus);
+		return;
+	    }
+	    
+	    message = gst_bus_pop (bus);
+	    if (message == NULL)
+		continue;
+
+	    rb_metadata_bus_handler (bus, message, md);
+	    switch (GST_MESSAGE_TYPE (message))
+	    { 
+		case GST_MESSAGE_EOS:
+		case GST_MESSAGE_ERROR:
+		    done = TRUE;
+		    break;
+		case GST_MESSAGE_APPLICATION:
+		    /* If this is our application message, time to 
+		     * exit */
+		    if (GST_MESSAGE_SRC (message) == GST_OBJECT (element))
+			done = TRUE;
+		    break;
+		default:
+		    break;
+	    }
+	    gst_message_unref (message);
+	}
+	gst_object_unref (bus);
+}
+
+
 void
 rb_metadata_load (RBMetaData *md,
 		  const char *uri,
@@ -544,6 +618,7 @@
 	GstElement *urisrc = NULL;
 	GstElement *decodebin = NULL;
 	GstElement *typefind = NULL;
+	GstElementStateReturn state_ret;
 
 	g_free (md->priv->uri);
 	md->priv->uri = NULL;
@@ -551,7 +626,6 @@
 	md->priv->type = NULL;
 	md->priv->error = NULL;
 	md->priv->eos = FALSE;
-	md->priv->handoff = FALSE;
 	md->priv->non_audio = FALSE;
 
 	if (md->priv->pipeline) {
@@ -599,14 +673,6 @@
  		goto out;
  	}
 
-	g_object_set (G_OBJECT (md->priv->sink), "signal-handoffs", TRUE, NULL);
- 
- 	g_signal_connect_object (pipeline, "error", G_CALLBACK (rb_metadata_gst_error_cb), md, 0);
- 	g_signal_connect_object (pipeline, "found-tag", G_CALLBACK (rb_metadata_gst_found_tag), md, 0);
-
-	g_signal_connect_object (md->priv->sink, "handoff", G_CALLBACK (rb_metadata_gst_fakesink_handoff_cb), md, 0);
-	g_signal_connect_object (md->priv->sink, "eos", G_CALLBACK (rb_metadata_gst_eos_cb), md, 0);
-
  	g_signal_connect_object (decodebin, "new-decoded-pad", G_CALLBACK (rb_metadata_gst_new_decoded_pad_cb), md, 0);
  	g_signal_connect_object (decodebin, "unknown-type", G_CALLBACK (rb_metadata_gst_unknown_type_cb), md, 0);
   
@@ -621,26 +687,36 @@
  
  	gst_element_link (urisrc, decodebin);
 
+	rb_debug ("going to PAUSED for metadata, uri: %s", uri);
 	md->priv->pipeline = pipeline;
-	gst_element_set_state (pipeline, GST_STATE_PLAYING);
-	while (gst_bin_iterate (GST_BIN (pipeline))
-	       && md->priv->error == NULL
-	       && !md->priv->handoff
-	       && !md->priv->eos)
-		;
 
-	if (md->priv->handoff) {
-		/* We caught the first buffer, which means the decoder should have read all
+	state_ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
+
+	if (state_ret == GST_STATE_SUCCESS) {
+		/* Post application specific message so we'll know when to stop
+		 * the message loop */
+		GstBus *bus;
+		bus = gst_element_get_bus (GST_ELEMENT (pipeline));
+		if (bus) {
+			gst_bus_post (bus, 
+			gst_message_new_application (GST_OBJECT (pipeline), NULL));
+			gst_object_unref (bus);
+		}
+
+		/* Poll the bus for messages */
+		rb_metadata_event_loop (md, GST_ELEMENT (pipeline));
+
+		/* We successfully went to PAUSED, which means the decoder should have read all
 		 * of the metadata, and should know the length now.
 		 */
 		if (g_hash_table_lookup (md->priv->metadata, GINT_TO_POINTER (RB_METADATA_FIELD_DURATION)) == NULL) {
 			GstFormat format = GST_FORMAT_TIME;
 			gint64 length;
 			
-			if (gst_element_query (md->priv->sink, GST_QUERY_TOTAL,
-					       &format, &length)) {
+			if (gst_element_query_position (md->priv->sink, &format, NULL, &length)) {
 				GValue *newval = g_new0 (GValue, 1);
 				
+				g_assert (format == GST_FORMAT_TIME);
 				rb_debug ("duration query succeeded");
 				
 				g_value_init (newval, G_TYPE_ULONG);
@@ -652,11 +728,13 @@
 				rb_debug ("duration query failed!");
 			}
 		}
-	} else if (md->priv->eos)
-		rb_debug ("caught eos without handoff!");
+	} 
+	
+	state_ret = gst_element_set_state (pipeline, GST_STATE_NULL);
+	if (state_ret == GST_STATE_ASYNC) {
+	    g_warning ("Failed to return metadata reader to NULL state");
+	}
 	
-	gst_element_set_state (pipeline, GST_STATE_NULL);
-
 	/* report errors for various failure cases.
 	 * these don't include the URI as the load failure dialog
 	 * already displays it.
@@ -685,7 +763,7 @@
 				     RB_METADATA_ERROR,
 				     RB_METADATA_ERROR_NOT_AUDIO_IGNORE,
 				     _("The file is not an audio stream, but is being ignored"));
-	} else if (!md->priv->handoff) {
+	} else if (state_ret != GST_STATE_SUCCESS) {
 		const char *report_type = rb_metadata_gst_type_to_name (md, md->priv->type);
 		if (report_type == NULL)
 			report_type = md->priv->type;
@@ -746,8 +824,6 @@
 	}
 }
 
-
-
 void
 rb_metadata_save (RBMetaData *md, GError **error)
 {
@@ -815,11 +891,9 @@
 
 	md->priv->pipeline = pipeline;
 	gst_element_set_state (pipeline, GST_STATE_PLAYING);
-	while (gst_bin_iterate (GST_BIN (pipeline))
-	       && md->priv->error == NULL
-	       && !md->priv->eos)
-		;
+	rb_metadata_event_loop (md, GST_ELEMENT (pipeline));
 	gst_element_set_state (pipeline, GST_STATE_NULL);
+
 	if (md->priv->error) {
 		g_propagate_error (error, md->priv->error);
 		goto out_error;
Index: player/rb-player-gst.c
===================================================================
RCS file: /cvs/gnome/rhythmbox/player/rb-player-gst.c,v
retrieving revision 1.41
diff -u -r1.41 rb-player-gst.c
--- player/rb-player-gst.c	26 Aug 2005 00:48:21 -0000	1.41
+++ player/rb-player-gst.c	27 Aug 2005 22:36:44 -0000
@@ -24,7 +24,6 @@
 #include <config.h>
 #include <gdk/gdk.h>
 #include <gst/gst.h>
-#include <gst/gconf/gconf.h>
 #include <math.h>
 #include <string.h>
 #include <stdlib.h>
@@ -51,9 +50,6 @@
 
 	gboolean playing;
 
-	guint error_signal_id;
-	guint buffering_signal_id;
-
 	float cur_volume;
 
 	guint tick_timeout_id;
@@ -172,11 +168,6 @@
 	g_source_remove (mp->priv->tick_timeout_id);
 
 	if (mp->priv->playbin) {
-		g_signal_handler_disconnect (G_OBJECT (mp->priv->playbin),
-					     mp->priv->error_signal_id);
-		g_signal_handler_disconnect (G_OBJECT (mp->priv->playbin),
-					     mp->priv->buffering_signal_id);
-		
 		gst_element_set_state (mp->priv->playbin,
 				       GST_STATE_NULL);
 		
@@ -245,52 +236,6 @@
 }
 
 static void
-eos_cb (GstElement *element,
-	RBPlayer *mp)
-{
-	RBPlayerSignal *signal;
-	signal = g_new0 (RBPlayerSignal, 1);
-	signal->type = EOS;
-	signal->object = mp;
-	g_object_ref (G_OBJECT (mp));
-	g_idle_add ((GSourceFunc) emit_signal_idle, signal);
-}
-
-static void
-error_cb (GstElement *element,
-	  GstElement *source,
-	  GError *error,
-	  gchar *debug,
-	  RBPlayer *mp)
-{
-	int code;
-	RBPlayerSignal *signal;
-
-	/* the handler shouldn't get called with error=NULL, but sometimes it does */
-	if (error == NULL)
-		return;
-
-	if ((error->domain == GST_CORE_ERROR)
-	    || (error->domain == GST_LIBRARY_ERROR)
-	    || (error->code == GST_RESOURCE_ERROR_BUSY)) {
-		code = RB_PLAYER_ERROR_NO_AUDIO;
-	} else {
-		code = RB_PLAYER_ERROR_GENERAL;
-	}
-
-	signal = g_new0 (RBPlayerSignal, 1);
-	signal->type = ERROR;
-	signal->object = mp;
-	signal->error = g_error_new_literal (RB_PLAYER_ERROR,
-					     code,
-					     error->message);
-
-	g_object_ref (G_OBJECT (mp));
-
-	g_idle_add ((GSourceFunc) emit_signal_idle, signal);
-}
-
-static void
 process_tag (const GstTagList *list, const gchar *tag, RBPlayer *player)
 {
 	int count;
@@ -333,27 +278,82 @@
 	g_idle_add ((GSourceFunc) emit_signal_idle, signal);
 }
 
-static void
-found_tag_cb (GObject *pipeline, GstElement *source, GstTagList *tags, RBPlayer *player)
+static gboolean
+rb_player_bus_cb (GstBus * bus, GstMessage * message,
+    RBPlayer *mp)
 {
-	gst_tag_list_foreach (tags, (GstTagForeachFunc) process_tag, player);
-}
+    g_return_val_if_fail (mp != NULL, FALSE);
 
-static void
-buffering_cb (GstElement *element, gint progress, RBPlayer *mp)
-{
-	RBPlayerSignal *signal;
+    switch (GST_MESSAGE_TYPE (message)) {
+	case GST_MESSAGE_ERROR: {
+	    char *debug;
+	    GError *error, *sig_error;
+	    int code;
+
+	    gst_message_parse_error (message, &error, &debug);
+
+	    if ((error->domain == GST_CORE_ERROR)
+		|| (error->domain == GST_LIBRARY_ERROR)
+		|| (error->code == GST_RESOURCE_ERROR_BUSY)) {
+		code = RB_PLAYER_ERROR_NO_AUDIO;
+	    } else {
+                code = RB_PLAYER_ERROR_GENERAL;
+	    }
+
+	    sig_error = g_error_new_literal (RB_PLAYER_ERROR,
+                                             code,
+                                             error->message);
+	    g_signal_emit (G_OBJECT (mp),
+			rb_player_signals[ERROR], 0,
+			sig_error);
+
+	    /* close if not already closing */
+	    if (mp->priv->uri != NULL)
+                rb_player_close (mp, NULL);
+
+	    g_error_free (error);
+	    g_free (debug);
+	    break;
+        }
+	case GST_MESSAGE_EOS:
+	    g_signal_emit (G_OBJECT (mp), rb_player_signals[EOS], 0);
+	    break;
+	case GST_MESSAGE_TAG: {
+	    GstTagList *tags;
+	    gst_message_parse_tag (message, &tags);
+
+	    gst_tag_list_foreach (tags, (GstTagForeachFunc) process_tag, mp);
+	    gst_tag_list_free (tags);
+	    break;
+	}
+	case GST_MESSAGE_BUFFERING: {
+	    RBPlayerSignal *signal;
+	    const GstStructure *s;
+	    gint progress;
+
+	    s = gst_message_get_structure (message);
+	    if (!gst_structure_get_int (s, "buffer-percent", &progress)) {
+		g_warning ("Could not get value from BUFFERING message");
+		break;
+	    }
 
-	signal = g_new0 (RBPlayerSignal, 1);
-	signal->type = BUFFERING;
+	    signal = g_new0 (RBPlayerSignal, 1);
+	    signal->type = BUFFERING;
 
-	g_object_ref (G_OBJECT (mp));
-	signal->object = mp;
+	    g_object_ref (G_OBJECT (mp));
+	    signal->object = mp;
 
-	signal->info = g_new0 (GValue, 1);
-	g_value_init (signal->info, G_TYPE_UINT);
-	g_value_set_uint (signal->info, (guint)progress);
-	g_idle_add ((GSourceFunc) emit_signal_idle, signal);
+	    signal->info = g_new0 (GValue, 1);
+	    g_value_init (signal->info, G_TYPE_UINT);
+	    g_value_set_uint (signal->info, (guint)progress);
+	    g_idle_add ((GSourceFunc) emit_signal_idle, signal);
+	    break;
+	} 
+	default:
+	    break;
+    }
+
+    return TRUE;
 }
 
 static gboolean
@@ -368,25 +368,17 @@
 	if (mp->priv->playbin == NULL) {
 		goto missing_element;
 	}
-	g_signal_connect_object (G_OBJECT (mp->priv->playbin),
-				 "found_tag",
-				 G_CALLBACK (found_tag_cb),
-				 mp, 0);
-
-	mp->priv->buffering_signal_id =
-		g_signal_connect_object (G_OBJECT (mp->priv->playbin),
-					 "buffering",
-					 G_CALLBACK (buffering_cb),
-					 mp, 0);
-	
-	mp->priv->error_signal_id =
-		g_signal_connect_object (G_OBJECT (mp->priv->playbin),
-					 "error",
-					 G_CALLBACK (error_cb),
-					 mp, 0);
+	/* Set the play timeout to 0, so we quickly return ASYNC from state change
+	 * requests, rather than block the GUI, and then watch for state change in the 
+	 * state transitions to make sure they happen */
+	/* FIXME: This breaks playbin. GStreamer needs fixing first */
+	// g_object_set (G_OBJECT (mp->priv->playbin), "play-timeout", (GstClockTime) 0, NULL);
+
+	gst_bus_add_watch (gst_element_get_bus (GST_ELEMENT (mp->priv->playbin)),
+			     (GstBusHandler) rb_player_bus_cb, mp);
 
 	/* Output sink */
-	sink = gst_gconf_get_default_audio_sink ();
+	sink = gst_element_factory_make ("gconfaudiosink", "audiosink");
 	if (sink == NULL) {
 		g_set_error (error,
 			     RB_PLAYER_ERROR,
@@ -397,8 +389,6 @@
 	}
 
 	g_object_set (G_OBJECT (mp->priv->playbin), "audio-sink", sink, NULL);
-	g_signal_connect_object (G_OBJECT (mp->priv->playbin), "eos",
-				 G_CALLBACK (eos_cb), mp, 0);
 
 	if (mp->priv->cur_volume > 1.0)
 		mp->priv->cur_volume = 1.0;
@@ -426,17 +416,6 @@
 rb_player_new (GError **error)
 {
 	RBPlayer *mp;
-	GstElement *dummy;
-
-	dummy = gst_element_factory_make ("fakesink", "fakesink");
-	if (!dummy
-	    || !gst_scheduler_factory_make (NULL, GST_ELEMENT (dummy))) {
-		g_set_error (error, RB_PLAYER_ERROR,
-			     RB_PLAYER_ERROR_GENERAL,
-			     "%s",
-			     _("Couldn't initialize scheduler.  Did you run gst-register?"));
-		return NULL;
-	}
 
 	mp = RB_PLAYER (g_object_new (RB_TYPE_PLAYER, NULL, NULL));
 
@@ -478,6 +457,11 @@
 			return FALSE;
 		}
 	}
+
+	/* FIXME: Set up a timeout or something and call gst_bin_watch_for_state_change
+	 * to catch if the pipeline doesn't go to PAUSED/PLAYING within some time (5 secs maybe?)
+	 */
+	gst_bin_watch_for_state_change (GST_BIN (mp->priv->playbin));
 	return TRUE;
 }
 
@@ -533,6 +517,7 @@
 			     _("Failed to close audio output sink"));
 		return FALSE;
 	}
+	gst_bin_watch_for_state_change (GST_BIN (mp->priv->playbin));
 	return TRUE;
 }
 
@@ -653,8 +638,7 @@
 	g_return_val_if_fail (RB_IS_PLAYER (mp), FALSE);
 	g_return_val_if_fail (mp->priv->playbin != NULL, FALSE);
 
-	/* FIXME we're lying here, no idea how to fix this though, without trying
-	 * a seek which might disrupt playback */
+	/* FIXME we're lying here. Need to send a seekable query on playbin */
 	return TRUE;
 }
 
@@ -666,16 +650,22 @@
 
 	g_return_if_fail (mp->priv->playbin != NULL);
 
-	gst_element_set_state (mp->priv->playbin, GST_STATE_PAUSED);
+	if (gst_element_set_state (mp->priv->playbin, GST_STATE_PAUSED) == GST_STATE_ASYNC) {
+	    /* FIXME: Use a timeout on get_state. Post a GError somewhere on failed? */
+	    if (gst_element_get_state (mp->priv->playbin, NULL, NULL, NULL) != GST_STATE_SUCCESS) {
+		g_warning ("Failed to pause pipeline before seek");
+	    }
+	}
 
-	gst_element_seek (mp->priv->playbin, 
-			  GST_FORMAT_TIME 
-			  | GST_SEEK_METHOD_SET 
-			  | GST_SEEK_FLAG_FLUSH, 
-			  time * GST_SECOND);
+	gst_element_seek (mp->priv->playbin, 1.0, 
+			  GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, 
+			  GST_SEEK_TYPE_SET, time * GST_SECOND,
+			  GST_SEEK_TYPE_NONE, -1);
 
-	if (mp->priv->playing)
+	if (mp->priv->playing) {
 		gst_element_set_state (mp->priv->playbin, GST_STATE_PLAYING);
+		gst_bin_watch_for_state_change (GST_BIN (mp->priv->playbin));
+	}
 }
 
 long
@@ -686,9 +676,11 @@
 	if (mp->priv->playbin != NULL) {
 		gint64 gst_position;
 		GstFormat fmt = GST_FORMAT_TIME;
-		gst_element_query (mp->priv->playbin, GST_QUERY_POSITION, &fmt, &gst_position);
+		gst_element_query_position (mp->priv->playbin, &fmt, &gst_position, NULL);
 	
-		return (long)(gst_position / (1000*1000*1000));
+		if (gst_position != -1)
+		    gst_position /= GST_SECOND;
+		return (long)(gst_position);
 	} else
 		return -1;
 }
Index: player/rb-recorder-gst.c
===================================================================
RCS file: /cvs/gnome/rhythmbox/player/rb-recorder-gst.c,v
retrieving revision 1.9
diff -u -r1.9 rb-recorder-gst.c
--- player/rb-recorder-gst.c	14 Jul 2005 23:15:52 -0000	1.9
+++ player/rb-recorder-gst.c	27 Aug 2005 22:36:46 -0000
@@ -31,8 +31,6 @@
 #include <fcntl.h>
 
 #include <gst/gst.h>
-#include <gst/gconf/gconf.h>
-#include <gst/play/play.h>
 #include <glib/gi18n.h>
 #include <libgnomevfs/gnome-vfs-utils.h>
 #include <nautilus-burn-recorder.h>
@@ -54,17 +52,14 @@
         GstElement *pipeline;
         
         GstElement *src;
-        GstPad     *src_pad;
         GstElement *decoder;
         GstElement *typefind;
         GstElement *audioconvert;
         GstElement *audioscale;
+        GstElement *capsfilter;
         GstElement *encoder;
         GstElement *sink;
 
-        guint       idle_id;
-        guint       error_signal_id;
-        guint       eos_signal_id;
         guint       tick_timeout_id;
 
         GTimer     *start_timer;
@@ -78,8 +73,7 @@
         NautilusBurnRecorder *recorder;
 
         gboolean    playing;
-
-        GError     *error;
+        gboolean    got_audio_pad;
 };
 
 typedef enum {
@@ -93,12 +87,6 @@
         LAST_SIGNAL
 } RBRecorderSignalType;
 
-typedef struct {
-        RBRecorder *object;
-        GError     *error;
-        GValue     *info;
-} RBRecorderSignal;
-
 static guint rb_recorder_signals [LAST_SIGNAL] = { 0 };
 
 static GObjectClass *parent_class = NULL;
@@ -234,29 +222,9 @@
                 }
         }
 
-        if (recorder->priv->idle_id > 0) {
-                g_source_remove (recorder->priv->idle_id);
-                recorder->priv->idle_id = 0;
-        }
-
-        if (recorder->priv->error_signal_id > 0) {
-                if (g_signal_handler_is_connected (G_OBJECT (recorder->priv->pipeline),
-                                                   recorder->priv->error_signal_id))
-                        g_signal_handler_disconnect (G_OBJECT (recorder->priv->pipeline),
-                                                     recorder->priv->error_signal_id);
-                recorder->priv->error_signal_id = 0;
-        }
-
-        if (recorder->priv->eos_signal_id > 0) {
-                if (g_signal_handler_is_connected (G_OBJECT (recorder->priv->pipeline),
-                                                   recorder->priv->eos_signal_id))
-                        g_signal_handler_disconnect (G_OBJECT (recorder->priv->pipeline),
-                                                     recorder->priv->eos_signal_id);
-                recorder->priv->eos_signal_id = 0;
-        }
-
         gst_object_unref (GST_OBJECT (recorder->priv->pipeline));
         recorder->priv->pipeline = NULL;
+	recorder->priv->got_audio_pad = FALSE;
 }
 
 static gboolean
@@ -283,62 +251,94 @@
 }
 
 static void
-eos_cb (GstElement *element,
-        RBRecorder *recorder)
+rb_recorder_gst_signal_error (RBRecorder *recorder,
+                              const char *msg)
 {
-        rb_debug ("EOS");
+        GError *error;
 
-        if (recorder->priv->pipeline)
-                gst_element_set_state (recorder->priv->pipeline, GST_STATE_NULL);
-
-        g_signal_emit (G_OBJECT (recorder), rb_recorder_signals [EOS], 0);
-}
+        error = g_error_new_literal (RB_RECORDER_ERROR,
+                                     RB_RECORDER_ERROR_GENERAL,
+                                     msg);
+	g_object_ref (recorder);
 
-static gboolean
-error_signal_idle (RBRecorderSignal *signal)
-{
-        g_signal_emit (G_OBJECT (signal->object),
+        g_signal_emit (G_OBJECT (recorder),
                        rb_recorder_signals [ERROR],
                        0,
-                       signal->error);
+                       error);
 
         /* close if not already closing */
-        if (signal->object->priv->src_uri != NULL)
-                rb_recorder_close (signal->object, NULL);
+        if (recorder->priv->src_uri != NULL)
+                rb_recorder_close (recorder, NULL);
 
-        g_object_unref (signal->object);
-        g_error_free (signal->error);
-        g_free (signal);
-
-        return FALSE;
+        g_object_unref (recorder);
+        g_error_free (error);
 }
 
-static void
-rb_recorder_gst_signal_error (RBRecorder *recorder,
-                              const char *msg)
+static gboolean
+pipe_message (GstBus *bus, GstMessage *message, RBRecorder *recorder)
 {
-        RBRecorderSignal *signal;
-
-        signal = g_new0 (RBRecorderSignal, 1);
-        signal->object = recorder;
-        signal->error = g_error_new_literal (RB_RECORDER_ERROR,
-                                             RB_RECORDER_ERROR_GENERAL,
-                                             msg);
-	g_object_ref (recorder);
+        switch (message->type) {
+          case GST_MESSAGE_EOS: 
+              rb_debug ("EOS");
+
+              if (recorder->priv->pipeline)
+                      gst_element_set_state (recorder->priv->pipeline, 
+                          GST_STATE_NULL);
+
+              g_signal_emit (G_OBJECT (recorder), 
+                      rb_recorder_signals [EOS], 0);
+              break;
+          case GST_MESSAGE_ERROR: {
+              GError *error;
+              gchar *debug;
+
+              rb_debug ("Error");
+              gst_message_parse_error (message, &error, &debug);
+              if (error) {
+                rb_recorder_gst_signal_error (recorder, error->message);
+                g_error_free (error);
+              }
+              else
+                rb_recorder_gst_signal_error (recorder, NULL);
+
+              g_free (debug);
+              break;
+          }
+          default:
+              break;
+        }
 
-        g_idle_add ((GSourceFunc)error_signal_idle, signal);
+        return TRUE;
 }
 
 static void
-error_cb (GstElement      *element,
-          GstElement      *source,
-          GError          *error,
-          gchar           *debug,
-          RBRecorder      *recorder)
-{
-        rb_debug ("Error");
+rb_recorder_new_pad_cb (GstElement *decodebin,
+                        GstPad     *pad,
+                        gboolean    last,
+                        RBRecorder *recorder)
+{
+	GstCaps      *caps;
+        GstStructure *str;
+        GstPad       *audio_pad;
+
+        audio_pad = gst_element_get_pad (recorder->priv->audioconvert, "sink");
+
+        /* Only link once. */
+        if (GST_PAD_IS_LINKED (audio_pad)) {
+                return;
+        }
+
+        /* Only link audio. */
+        caps = gst_pad_get_caps (pad);
+        str = gst_caps_get_structure (caps, 0);
+        if (!g_strrstr (gst_structure_get_name (str), "audio")) {
+                gst_caps_unref (caps);
+                return;
+        }
 
-        rb_recorder_gst_signal_error (recorder, error->message);
+        gst_caps_unref (caps);
+        if (gst_pad_link (pad, audio_pad))
+	    recorder->priv->got_audio_pad = TRUE;
 }
 
 static void
@@ -348,6 +348,7 @@
 {
         char    *element_name = NULL;
         GstCaps *filtercaps;
+        GstBus  *bus;
 
 #define MAKE_ELEMENT_OR_LOSE(NAME, NICE) G_STMT_START {                 \
                 element_name = #NAME ;                                  \
@@ -360,7 +361,7 @@
         rb_recorder_gst_free_pipeline (recorder);
 
         /* The recording pipeline looks like:
-         *  { src ! spider ! audioconvert ! audioscale
+         *  { src ! decodebin ! audioconvert ! audioscale
          *    ! audio/x-raw-int,rate=44100,width=16,depth=16 ! wavenc ! sink }
          */
 
@@ -374,36 +375,37 @@
                 return;
         }
 
-        recorder->priv->error_signal_id =
-                g_signal_connect_object (G_OBJECT (recorder->priv->pipeline),
-                                         "error",
-                                         G_CALLBACK (error_cb),
-                                         recorder, 0);
+        bus = gst_element_get_bus (recorder->priv->pipeline);
+        gst_bus_add_watch (bus, (GstBusHandler) pipe_message, recorder);
+        gst_object_unref (bus);
 
         /* Construct elements */
 
         /* The source */
-
         MAKE_ELEMENT_OR_LOSE(gnomevfssrc, src);
         gst_bin_add (GST_BIN (recorder->priv->pipeline), recorder->priv->src);
 
-        recorder->priv->src_pad = gst_element_get_pad (recorder->priv->src, "src");
-        g_assert (recorder->priv->src_pad); /* TODO: GError */
-
         /* The queue */
 
         MAKE_ELEMENT_OR_LOSE(typefind, typefind);
         gst_bin_add (GST_BIN (recorder->priv->pipeline), recorder->priv->typefind);
 
-        MAKE_ELEMENT_OR_LOSE(spider, decoder);
+        MAKE_ELEMENT_OR_LOSE(decodebin, decoder);
         gst_bin_add (GST_BIN (recorder->priv->pipeline), recorder->priv->decoder);
+        g_signal_connect_object (G_OBJECT (recorder->priv->decoder), 
+            "new_decoded_pad", G_CALLBACK (rb_recorder_new_pad_cb), 
+            recorder, 0);
 
         MAKE_ELEMENT_OR_LOSE(audioconvert, audioconvert);
         gst_bin_add (GST_BIN (recorder->priv->pipeline), recorder->priv->audioconvert);
 
-        MAKE_ELEMENT_OR_LOSE(audioscale, audioscale);
+        /* FIXME: restore audioscale element once ported */
+        MAKE_ELEMENT_OR_LOSE(identity, audioscale);
         gst_bin_add (GST_BIN (recorder->priv->pipeline), recorder->priv->audioscale);
 
+        MAKE_ELEMENT_OR_LOSE(capsfilter, capsfilter);
+        gst_bin_add (GST_BIN (recorder->priv->pipeline), recorder->priv->capsfilter);
+
         MAKE_ELEMENT_OR_LOSE(wavenc, encoder);
         gst_bin_add (GST_BIN (recorder->priv->pipeline), recorder->priv->encoder);
 
@@ -421,30 +423,26 @@
         }
         gst_bin_add (GST_BIN (recorder->priv->pipeline), recorder->priv->sink);
 
-        gst_element_link_many (recorder->priv->src,
-                               recorder->priv->typefind,
-                               recorder->priv->decoder,
-                               recorder->priv->audioconvert,
-                               recorder->priv->audioscale,
-                               NULL);
-
         filtercaps = gst_caps_new_simple ("audio/x-raw-int",
                                           "channels", G_TYPE_INT, 2,
                                           "rate",     G_TYPE_INT, 44100,
                                           "width",    G_TYPE_INT, 16,
                                           "depth",    G_TYPE_INT, 16,
                                           NULL);
-        gst_element_link_filtered (recorder->priv->audioscale,
-                                   recorder->priv->encoder,
-                                   filtercaps);
-        gst_caps_free (filtercaps);
-
-        gst_element_link (recorder->priv->encoder,
-                          recorder->priv->sink);
-
-        recorder->priv->eos_signal_id =
-                g_signal_connect_object (G_OBJECT (recorder->priv->pipeline), "eos",
-                                         G_CALLBACK (eos_cb), recorder, 0);
+	g_object_set (recorder->priv->capsfilter, "filter-caps", 
+		filtercaps, NULL);
+
+        gst_element_link_many (recorder->priv->src,
+                               recorder->priv->typefind,
+                               recorder->priv->decoder,
+			       NULL);
+
+        gst_element_link_many (recorder->priv->audioconvert,
+                               recorder->priv->audioscale,
+                               recorder->priv->capsfilter,
+                               recorder->priv->encoder,
+			       recorder->priv->sink,
+                               NULL);
 
         rb_debug ("Pipeline construction complete");
         return;
@@ -509,19 +507,9 @@
 rb_recorder_new (GError **error)
 {
         RBRecorder *recorder;
-        GstElement *dummy;
 
         rb_debug ("New rb_recorder");
 
-        dummy = gst_element_factory_make ("fakesink", "fakesink");
-        if (!dummy
-            || !gst_scheduler_factory_make (NULL, GST_ELEMENT (dummy))) {
-                g_set_error (error, RB_RECORDER_ERROR,
-                             RB_RECORDER_ERROR_GENERAL,
-                             _("Couldn't initialize scheduler.  Did you run gst-register?"));
-                return NULL;
-        }
-
         recorder = g_object_new (RB_TYPE_RECORDER, NULL, NULL);
 
         return recorder;
@@ -535,14 +523,20 @@
         double           rate;
         double           elapsed;
         double           secs;
-        static GstFormat format = GST_FORMAT_BYTES;
+        GstFormat        format = GST_FORMAT_BYTES;
+	GstElementState  state;
 
         g_return_val_if_fail (recorder != NULL, FALSE);
         g_return_val_if_fail (RB_IS_RECORDER (recorder), FALSE);
         g_return_val_if_fail (recorder->priv != NULL, FALSE);
         g_return_val_if_fail (recorder->priv->pipeline != NULL, FALSE);
 
-        if (gst_element_get_state (recorder->priv->pipeline) != GST_STATE_PLAYING) {
+        if (!gst_element_get_state (recorder->priv->pipeline, &state, 
+            NULL, NULL)) {
+                g_warning (_("Could not retrieve state from processing pipeline"));
+                return TRUE;
+	}
+        if (state != GST_STATE_PLAYING) {
                 recorder->priv->tick_timeout_id = 0;
                 if (recorder->priv->start_timer) {
                         g_timer_destroy (recorder->priv->start_timer);
@@ -551,12 +545,8 @@
                 return FALSE;
         }
 
-        if (!gst_pad_query (recorder->priv->src_pad, GST_QUERY_POSITION, &format, &position)) {
-                g_warning (_("Could not get current track position"));
-                return TRUE;
-        }
-
-        if (!gst_pad_query (recorder->priv->src_pad, GST_QUERY_TOTAL, &format, &total)) {
+        if (!gst_element_query_position (recorder->priv->src, &format, 
+            &position, &total)) {
                 g_warning (_("Could not get current track position"));
                 return TRUE;
         }
@@ -585,9 +575,6 @@
                                fraction, (long)secs);
         }
 
-        /* Extra kick in the pants to keep things moving on a busy system */
-        gst_bin_iterate (GST_BIN (recorder->priv->pipeline));
-
         return TRUE;
 }
 
@@ -611,11 +598,9 @@
                                      _("Could not start pipeline playing"));
                         return FALSE;
                 }                               
-                recorder->priv->idle_id = g_idle_add ((GSourceFunc)gst_bin_iterate,
-                                                      GST_BIN (recorder->priv->pipeline));
-                recorder->priv->tick_timeout_id = g_timeout_add (200,
-                                                                 (GSourceFunc)tick_timeout_cb,
-                                                                 recorder);
+                recorder->priv->tick_timeout_id = 
+			g_timeout_add (200, (GSourceFunc)tick_timeout_cb,
+                        recorder);
         } else {
                 rb_debug ("Pausing pipeline");
                 if (gst_element_set_state (recorder->priv->pipeline,
@@ -626,10 +611,6 @@
                                      _("Could not pause playback"));
                         return FALSE;
                 }
-                if (recorder->priv->idle_id > 0) {
-                        g_source_remove (recorder->priv->idle_id);
-                        recorder->priv->idle_id = 0;
-                }
                 if (recorder->priv->tick_timeout_id > 0) {
                         g_source_remove (recorder->priv->tick_timeout_id);
                         recorder->priv->tick_timeout_id = 0;
@@ -652,6 +633,7 @@
         rb_debug ("Closing rb_recorder");
 
         recorder->priv->playing = FALSE;
+        recorder->priv->got_audio_pad = FALSE;
 
         g_free (recorder->priv->src_uri);
         recorder->priv->src_uri = NULL;
@@ -726,11 +708,7 @@
         if (error && *error)
                 return;
                 
-        if (recorder->priv->idle_id > 0) {
-                g_source_remove (recorder->priv->idle_id);
-                recorder->priv->idle_id = 0;
-        }
-
+	recorder->priv->got_audio_pad = FALSE;
         g_object_set (G_OBJECT (recorder->priv->src), "iradio-mode", FALSE, NULL);
         gst_element_set_state (recorder->priv->src, GST_STATE_NULL);
         g_object_set (G_OBJECT (recorder->priv->src), "location", src_uri, NULL);
Index: shell/main.c
===================================================================
RCS file: /cvs/gnome/rhythmbox/shell/main.c,v
retrieving revision 1.67
diff -u -r1.67 main.c
--- shell/main.c	26 Aug 2005 11:10:43 -0000	1.67
+++ shell/main.c	27 Aug 2005 22:36:46 -0000
@@ -34,8 +34,6 @@
 #include <string.h>
 #ifdef HAVE_GSTREAMER
 #include <gst/gst.h>
-#include <gst/gconf/gconf.h>
-#include <gst/control/control.h>
 #endif
 #ifdef WITH_MONKEYMEDIA
 #include "monkey-media.h"
@@ -203,9 +201,6 @@
 	textdomain (GETTEXT_PACKAGE);
 #endif
 
-#ifdef HAVE_GSTREAMER	
-	gst_control_init (&argc, &argv);
-#endif
 #ifdef WITH_MONKEYMEDIA
 	monkey_media_init (&argc, &argv);
 #endif
