Index: configure.ac
===================================================================
RCS file: /cvs/gnome/rhythmbox/configure.ac,v
retrieving revision 1.200
diff -u -u -r1.200 configure.ac
--- configure.ac	6 Jan 2006 02:53:42 -0000	1.200
+++ configure.ac	8 Jan 2006 09:11:51 -0000
@@ -152,6 +152,7 @@
 GST_0_10_REQUIRED_VERSION=0.9.7
 PKG_CHECK_MODULES(GSTREAMER_0_10, \
 	gstreamer-$GST_0_10_MAJORMINOR >= $GST_0_10_REQUIRED_VERSION
+	gstreamer-base-$GST_0_10_MAJORMINOR >= $GST_0_10_REQUIRED_VERSION
 	gstreamer-plugins-base-$GST_0_10_MAJORMINOR >= $GST_0_10_REQUIRED_VERSION,
 	have_gstreamer_0_10=yes,have_gstreamer_0_10=no)
 
@@ -186,6 +187,8 @@
 		AC_MSG_ERROR([GStreamer 0.8 explicity requested, and not found or older than version $GST_REQUIRED_VERSION])
 	fi
 fi
+AM_CONDITIONAL(USE_GSTREAMER_0_10, test x"$with_playback" = xgstreamer_0_10)
+AM_CONDITIONAL(USE_GSTREAMER_0_8, test x"$with_playback" = xgstreamer_0_8)
 
 dnl Give error and exit if we don't have gstreamer
 if test x$with_playback = xauto; then
@@ -217,10 +220,6 @@
 	      AC_HELP_STRING([--enable-daap],
 			     [Enable Digital Audio Access Protocol (music sharing) in rhythmbox **EXPERIMENTAL**]))
 if test x"$enable_daap" = xyes; then
-   if test x"$with_playback" = xgstreamer_0_10; then
-      AC_MSG_ERROR([DAAP support cannot currently be used with GStreamer 0.10])
-   fi
-
    AC_MSG_WARN([DAAP support is experimental, and may cause Rhythmbox to crash uncontrollably, use at your own risk])
 fi
 
Index: daapsharing/Makefile.am
===================================================================
RCS file: /cvs/gnome/rhythmbox/daapsharing/Makefile.am,v
retrieving revision 1.2
diff -u -u -r1.2 Makefile.am
--- daapsharing/Makefile.am	9 Sep 2005 10:08:52 -0000	1.2
+++ daapsharing/Makefile.am	8 Jan 2006 09:11:51 -0000
@@ -14,11 +14,19 @@
 		rb-daap-mdns.h 		\
 		rb-daap-connection.c 	\
 		rb-daap-connection.h 	\
-		rb-daap-src.c 		\
 		rb-daap-src.h		\
 		rb-daap-dialog.c	\
 		rb-daap-dialog.h
 endif
+
+if USE_GSTREAMER_0_10
+libdaapsharing_la_SOURCES +=		\
+		rb-daap-src-gst-0.10.c
+else
+libdaapsharing_la_SOURCES +=		\
+		rb-daap-src.c
+endif
+
 
 INCLUDES =						\
         -DGNOMELOCALEDIR=\""$(datadir)/locale"\"        \
Index: daapsharing/rb-daap-src.c
===================================================================
RCS file: /cvs/gnome/rhythmbox/daapsharing/rb-daap-src.c,v
retrieving revision 1.5
diff -u -u -r1.5 rb-daap-src.c
--- daapsharing/rb-daap-src.c	6 Jan 2006 02:53:43 -0000	1.5
+++ daapsharing/rb-daap-src.c	8 Jan 2006 09:11:52 -0000
@@ -78,6 +78,9 @@
 	gint64 curoffset;
 	gint64 seek_bytes;
 	guint32 bytes_per_read;
+
+	glong seek_time;
+	glong seek_time_to_return;
 };
 
 struct _RBDAAPSrcClass
@@ -521,9 +524,6 @@
 	return gst_caps_new_any ();
 }
 
-static glong seek_time = 0;
-static glong seek_time_to_return = 0;
-
 static char *
 get_headers (RBDAAPSrc *src)
 {
@@ -531,13 +531,13 @@
 	gchar *headers;
 
 	source = rb_daap_source_find_for_uri (src->daap_uri);
-	headers = rb_daap_source_get_headers (source, src->daap_uri, seek_time, &(src->seek_bytes));
+	headers = rb_daap_source_get_headers (source, src->daap_uri, src->seek_time, &(src->seek_bytes));
 	if (src->seek_bytes) {
 		src->send_discont = TRUE;
 		src->need_flush = TRUE;
 	}
-	seek_time_to_return = seek_time;
-	seek_time = 0;
+	src->seek_time_to_return = seek_time;
+	src->seek_time = 0;
 
 	return headers;
 }
@@ -704,7 +704,7 @@
 	gchar *request = NULL;
 	gchar *headers = NULL;
 
-	seek_time_to_return = 0;
+	src->seek_time_to_return = 0;
 	
 	if (src->sock_fd != -1) {
 		close (src->sock_fd);
@@ -953,32 +953,16 @@
 			  "GPL",
 			  PACKAGE,
 			  "");
-
-static gboolean src_initialized = FALSE;
-
-void
-rb_daap_src_initialize ()
-{
-	if (src_initialized == FALSE) {
-		seek_time = 0;
-		src_initialized = TRUE;
-	}
-}
-
-void
-rb_daap_src_shutdown ()
-{
-	src_initialized = FALSE;
-}
-
 void
-rb_daap_src_set_time (glong time)
+rb_daap_src_set_time (GstElement *element, glong time)
 {
-	seek_time = time;
+	RBDAAPSrc *src = RB_DAAP_SRC (element);
+	src->seek_time = time;
 }
 
 glong
-rb_daap_src_get_time ()
+rb_daap_src_get_time (GstElement *element)
 {
-	return seek_time_to_return;
+	RBDAAPSrc *src = RB_DAAP_SRC (element);
+	return src->seek_time_to_return;
 }
Index: daapsharing/rb-daap-src.h
===================================================================
RCS file: /cvs/gnome/rhythmbox/daapsharing/rb-daap-src.h,v
retrieving revision 1.2
diff -u -u -r1.2 rb-daap-src.h
--- daapsharing/rb-daap-src.h	6 Jan 2006 02:53:43 -0000	1.2
+++ daapsharing/rb-daap-src.h	8 Jan 2006 09:11:52 -0000
@@ -23,14 +23,12 @@
 #define __RB_DAAP_SRC_H
 
 #include <glib.h>
+#include <gst/gstelement.h>
 
 G_BEGIN_DECLS
 
-void rb_daap_src_initialize (void);
-void rb_daap_src_shutdown (void);
-
-void rb_daap_src_set_time (glong time);
-glong rb_daap_src_get_time (void);
+void rb_daap_src_set_time (GstElement *element, glong time);
+glong rb_daap_src_get_time (GstElement *element);
 
 G_END_DECLS
 
Index: player/rb-player-gst.c
===================================================================
RCS file: /cvs/gnome/rhythmbox/player/rb-player-gst.c,v
retrieving revision 1.54
diff -u -u -r1.54 rb-player-gst.c
--- player/rb-player-gst.c	20 Dec 2005 10:11:29 -0000	1.54
+++ player/rb-player-gst.c	8 Jan 2006 09:11:53 -0000
@@ -991,7 +991,11 @@
 	 * So, we do it this way.  Doesn't that suck?
 	 */
 	if (mp->priv->uri && g_strncasecmp (mp->priv->uri, "daap://", 7) == 0) {
-		rb_daap_src_set_time (time);
+		GstElement *src;
+
+		src = gst_bin_get_by_interface (GST_BIN (mp->priv->playbin), GST_TYPE_URI_HANDLER);
+		if (src)
+			rb_daap_src_set_time (src, time);
 	} else {
 #endif
 #ifdef HAVE_GSTREAMER_0_8
@@ -1034,7 +1038,10 @@
 
 #ifdef WITH_DAAP_SUPPORT
 		if (mp->priv->uri && g_strncasecmp (mp->priv->uri, "daap://", 7) == 0) {
-			position += rb_daap_src_get_time ();
+			GstElement *src;
+			src = gst_bin_get_by_interface (GST_BIN (mp->priv->playbin), GST_TYPE_URI_HANDLER);
+			if (src) 
+				position += rb_daap_src_get_time (src);
 		}
 #endif
 
Index: sources/rb-daap-source.c
===================================================================
RCS file: /cvs/gnome/rhythmbox/sources/rb-daap-source.c,v
retrieving revision 1.15
diff -u -u -r1.15 rb-daap-source.c
--- sources/rb-daap-source.c	6 Jan 2006 02:53:44 -0000	1.15
+++ sources/rb-daap-source.c	8 Jan 2006 09:11:53 -0000
@@ -39,7 +39,6 @@
 
 #include "rb-daap-connection.h"
 #include "rb-daap-mdns.h"
-#include "rb-daap-src.h"
 
 #include "rb-static-playlist-source.h"
 
@@ -431,8 +430,6 @@
 		       				 	  (GEqualFunc)g_str_equal, 
 							  (GDestroyNotify)g_free, 
 							  (GDestroyNotify)stop_resolver);
-
-	rb_daap_src_initialize ();
 }
 
 static void
@@ -460,8 +457,6 @@
 		rb_daap_mdns_browse_cancel (browser);
 		browser = 0;
 	}
-
-	rb_daap_src_shutdown ();
 }
 
 static void
--- /dev/null	2006-01-08 11:56:15.602345336 +1100
+++ daapsharing/rb-daap-src-gst-0.10.c	2006-01-08 19:17:54.000000000 +1100
@@ -0,0 +1,657 @@
+/*
+ *  Implementatin of DAAP (iTunes Music Sharing) GStreamer source
+ *
+ *  Copyright (C) 2005 Charles Schmidt <cschmidt2@emich.edu>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include "rb-daap-src.h"
+#include "rb-daap-source.h"
+
+#include <string.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/ioctl.h>
+#include <netdb.h>
+#include <unistd.h>
+
+#include <libgnome/gnome-i18n.h>
+#include <gst/gst.h>
+#include <gst/base/gstbasesrc.h>
+#include <gst/base/gstpushsrc.h>
+
+#define RB_TYPE_DAAP_SRC (rb_daap_src_get_type())
+#define RB_DAAP_SRC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),RB_TYPE_DAAP_SRC,RBDAAPSrc))
+#define RB_DAAP_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),RB_TYPE_DAAP_SRC,RBDAAPSrcClass))
+#define RB_IS_DAAP_SRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),RB_TYPE_DAAP_SRC))
+#define RB_IS_DAAP_SRC_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),RB_TYPE_DAAP_SRC))
+
+typedef struct _RBDAAPSrc RBDAAPSrc;
+typedef struct _RBDAAPSrcClass RBDAAPSrcClass;
+
+struct _RBDAAPSrc
+{
+	GstPushSrc parent;
+
+	/* uri */
+	gchar *http_uri;
+	gchar *daap_uri;
+
+	/* connection */
+	int port;
+	gchar *host;
+	gchar *path;
+	struct sockaddr_in server_sockaddr;
+	int sock_fd;
+	
+	gint64 curoffset;
+
+	gint64 seek_bytes;
+	glong seek_time;
+	gboolean do_seek;
+};
+
+struct _RBDAAPSrcClass
+{
+	GstPushSrcClass parent_class;
+};
+
+static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
+	GST_PAD_SRC,
+	GST_PAD_ALWAYS,
+	GST_STATIC_CAPS_ANY);
+
+GST_DEBUG_CATEGORY_STATIC (rb_daap_src_debug);
+#define GST_CAT_DEFAULT rb_daap_src_debug
+
+static GstElementDetails rb_daap_src_details =
+GST_ELEMENT_DETAILS ("RBDAAP Source",
+	"Source/File",
+	"Read a DAAP (music share) file",
+	"Charles Schmidt <cschmidt2@emich.edu");
+
+enum
+{
+	PROP_0,
+	PROP_LOCATION,
+};
+
+static GType rb_daap_src_get_type (void);
+static void rb_daap_src_uri_handler_init (gpointer g_iface, gpointer iface_data);
+
+static void
+_do_init (GType daap_src_type)
+{
+	static const GInterfaceInfo urihandler_info = {
+		rb_daap_src_uri_handler_init,
+		NULL,
+		NULL
+	};
+
+	g_type_add_interface_static (daap_src_type, GST_TYPE_URI_HANDLER,
+			&urihandler_info);
+
+	GST_DEBUG_CATEGORY_INIT (rb_daap_src_debug, "daapsrc", 0, "daapsrc element");
+}
+
+GST_BOILERPLATE_FULL (RBDAAPSrc, rb_daap_src, GstPushSrc, GST_TYPE_PUSH_SRC, _do_init);
+
+static void rb_daap_src_set_property (GObject *object,
+			  guint prop_id,
+			  const GValue *value,
+			  GParamSpec *pspec);
+static void rb_daap_src_get_property (GObject *object,
+		          guint prop_id,
+			  GValue *value,
+			  GParamSpec *pspec);
+static void rb_daap_src_finalize (GObject *object);
+
+static gboolean rb_daap_src_start (GstBaseSrc *bsrc);
+static gboolean rb_daap_src_stop (GstBaseSrc *bsrc);
+static gboolean rb_daap_src_is_seekable (GstBaseSrc *bsrc);
+static gboolean rb_daap_src_get_size (GstBaseSrc *src, guint64 *size);
+static GstFlowReturn rb_daap_src_create (GstPushSrc *psrc, GstBuffer **outbuf);
+
+static void
+rb_daap_src_base_init (gpointer g_class)
+{
+	GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
+
+	gst_element_class_add_pad_template (gstelement_class,
+		gst_static_pad_template_get (&srctemplate));
+	gst_element_class_set_details (gstelement_class, &rb_daap_src_details);
+}
+
+static void 
+rb_daap_src_class_init (RBDAAPSrcClass *klass)
+{
+	GObjectClass *gobject_class;
+	GstElementClass *gstelement_class;
+	GstBaseSrcClass *gstbasesrc_class;
+	GstPushSrcClass *gstpushsrc_class;
+
+	gobject_class = G_OBJECT_CLASS (klass);
+	gstelement_class = GST_ELEMENT_CLASS (klass);
+	gstbasesrc_class = (GstBaseSrcClass *) klass;
+	gstpushsrc_class = (GstPushSrcClass *) klass;
+
+	parent_class = g_type_class_ref (GST_TYPE_PUSH_SRC);
+
+	gobject_class->set_property = rb_daap_src_set_property;
+	gobject_class->get_property = rb_daap_src_get_property;
+	gobject_class->finalize = rb_daap_src_finalize;
+
+	g_object_class_install_property (gobject_class, PROP_LOCATION,
+			g_param_spec_string ("location", 
+					     "file location",
+					     "location of the file to read",
+					     NULL,
+					     G_PARAM_READWRITE));
+
+	gstbasesrc_class->start = GST_DEBUG_FUNCPTR (rb_daap_src_start);
+	gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (rb_daap_src_stop);
+	gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (rb_daap_src_is_seekable);
+	gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (rb_daap_src_get_size);
+
+	gstpushsrc_class->create = GST_DEBUG_FUNCPTR (rb_daap_src_create);
+}
+
+static void
+rb_daap_src_init (RBDAAPSrc *src, RBDAAPSrcClass *klass)
+{
+	src->http_uri = NULL;
+	src->daap_uri = NULL;
+	src->port = 0;
+	src->host = NULL;
+	src->path = NULL;
+	src->sock_fd = -1;
+}
+
+static void
+rb_daap_src_free_location (RBDAAPSrc *src)
+{
+	g_free (src->http_uri);
+	g_free (src->daap_uri);
+	g_free (src->host);
+	g_free (src->path);
+	
+	src->http_uri = NULL;
+	src->daap_uri = NULL;
+	src->host = NULL;
+	src->path = NULL;
+}
+
+static void
+rb_daap_src_finalize (GObject *object)
+{
+	RBDAAPSrc *src;
+	src = RB_DAAP_SRC (object);
+	
+	rb_daap_src_free_location (src);
+	if (src->sock_fd != -1)
+		close (src->sock_fd);
+
+	G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static gboolean
+rb_daap_src_set_location (RBDAAPSrc *src, const gchar *location)
+{
+	const gchar *pathstart = NULL;
+	const gchar *hostport = NULL;
+	const gchar *portstart = NULL;
+	gint locationlen;
+
+	GST_STATE_LOCK (src);
+	{
+		GstState state;
+		state = GST_STATE (src);
+		if (state != GST_STATE_READY && state != GST_STATE_NULL) {
+			GST_DEBUG_OBJECT (src, "setting location in wrong state");
+			GST_STATE_UNLOCK (src);
+			return FALSE;
+		}
+	}
+	GST_STATE_UNLOCK (src);
+
+	rb_daap_src_free_location (src);
+
+	src->daap_uri = g_strdup (location);
+	src->http_uri = g_strconcat ("http", location + 4, NULL);
+
+	locationlen = strlen (location);
+	hostport = location + 7;
+	pathstart = strchr (hostport, '/');
+
+	if (pathstart) {
+		src->path = g_strdup (pathstart);
+	} else {
+		src->path = g_strdup ("/");
+		pathstart = location + locationlen;
+	}
+	
+	portstart = strrchr (hostport, ':');
+	if (portstart) {
+		src->host = g_strndup (hostport, portstart - hostport);
+		src->port = strtoul (portstart + 1, NULL, 0);
+	} else {
+		src->host = g_strndup (hostport, pathstart - hostport);
+		src->port = 3869;
+	}
+
+	g_object_notify (G_OBJECT (src), "location");
+	gst_uri_handler_new_uri (GST_URI_HANDLER (src), src->http_uri);
+	return TRUE;
+}
+
+static void
+rb_daap_src_set_property (GObject *object,
+			  guint prop_id,
+			  const GValue *value,
+			  GParamSpec *pspec)
+{
+	RBDAAPSrc *src = RB_DAAP_SRC (object);
+
+	switch (prop_id) {
+	case PROP_LOCATION:
+		rb_daap_src_set_location (src, g_value_get_string (value));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+rb_daap_src_get_property (GObject *object,
+		          guint prop_id,
+			  GValue *value,
+			  GParamSpec *pspec)
+{
+	RBDAAPSrc *src = RB_DAAP_SRC (object);
+
+	switch (prop_id) {
+	case PROP_LOCATION:
+		g_value_set_string (value, src->daap_uri);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+/* read number of bytes from a socket into a given buffer incrementally.
+ * Returns number of bytes read with same semantics as read(2):
+ * < 0: error, see errno
+ * = 0: EOF
+ * > 0: bytes read
+ */
+static gint
+gst_tcp_socket_read (int socket, guchar *buf, size_t count)
+{
+	size_t bytes_read = 0;
+
+	while (bytes_read < count) {
+		ssize_t ret = read (socket, buf + bytes_read, count - bytes_read);
+
+		if (ret < 0) {
+			GST_WARNING ("error while reading: %s", g_strerror (errno));
+			return ret;
+		}
+		if (ret == 0)
+			break;
+		bytes_read += ret;
+	}
+
+	GST_LOG ("read %d bytes succesfully", bytes_read);
+	return bytes_read;
+}
+
+static gint
+gst_tcp_socket_write (int socket, const guchar *buf, size_t count)
+{
+	size_t bytes_written = 0;
+
+	while (bytes_written < count) {
+		ssize_t wrote = send (socket, buf + bytes_written, count - bytes_written, MSG_NOSIGNAL);
+
+		if (wrote < 0) {
+			GST_WARNING ("error while writing: %s", g_strerror (errno));
+			return wrote;
+		}
+		if (wrote == 0)
+			break;
+
+		bytes_written += wrote;
+	}
+
+	GST_LOG ("wrote %d bytes succesfully", bytes_written);
+	return bytes_written;
+}
+
+static char *
+get_headers (RBDAAPSrc *src)
+{
+	RBDAAPSource *source = NULL;
+	gchar *headers;
+
+	source = rb_daap_source_find_for_uri (src->daap_uri);
+	headers = rb_daap_source_get_headers (source, src->daap_uri, src->seek_time, &(src->seek_bytes));
+	src->do_seek = FALSE;
+
+	return headers;
+}
+
+
+static gboolean
+rb_daap_src_start (GstBaseSrc *bsrc)
+{
+	int ret;
+	gchar *request = NULL;
+	gchar *headers = NULL;
+	RBDAAPSrc *src = RB_DAAP_SRC (bsrc);
+
+	if (src->sock_fd != -1) {
+		return TRUE;
+	}
+	src->curoffset = 0;
+
+	if ((src->sock_fd = socket (AF_INET, SOCK_STREAM, 0)) == -1) {
+		GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), GST_ERROR_SYSTEM);
+		return FALSE;
+	}
+
+	src->server_sockaddr.sin_family = AF_INET;
+	src->server_sockaddr.sin_port = htons (src->port);
+	src->server_sockaddr.sin_addr.s_addr = inet_addr (src->host);
+	memset (&(src->server_sockaddr.sin_zero), '\0', 8);
+	
+	/* connect to server */
+	GST_DEBUG_OBJECT (src, "connecting to server ip=%s port=%d ",
+				src->host, src->port);
+	ret = connect (src->sock_fd, (struct sockaddr *) &(src->server_sockaddr), sizeof (struct sockaddr));
+
+	if (ret) {
+		switch (errno) {
+			case ECONNREFUSED:
+				GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
+						(_("Connection to %s:%d refused."), src->host, src->port),
+						(NULL));
+				return FALSE;
+			default:
+				GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
+						("connect to %s:%d failed: %s", src->host, src->port,
+								g_strerror (errno)));
+				return FALSE;
+		}
+	}
+
+	/* send request and headers */
+	headers = get_headers (src);
+	request = g_strdup_printf ("GET %s HTTP/1.1\r\nHost: %s\r\n%s\r\n",
+				   src->path, src->host, headers);
+	g_free (headers);
+	GST_DEBUG_OBJECT (src, "sending request %s", request);
+	if (gst_tcp_socket_write (src->sock_fd, (guchar *)request, strlen(request)) <= 0) {
+				GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
+						("sending HTTP request to %s failed: %s", src->daap_uri,
+								g_strerror (errno)));
+				return FALSE;
+	}
+	g_free(request);
+
+	/* receive and discard headers */
+	/* FIXME this part is slow
+	 * FIXME we should, i think, find the size from these so we can use it
+	 * later
+	 */
+	{
+		guchar responseline[12];
+		gint rc;
+		/* receive response line (HTTP/1.x NNN) */
+		if ((rc = gst_tcp_socket_read(src->sock_fd, (guchar *)responseline, sizeof(responseline))) <= 0) {
+			GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
+			 ("reading HTTP response from %s failed: %s", src->daap_uri,
+				g_strerror (errno)));
+			return FALSE;
+		}
+		GST_DEBUG_OBJECT(src, "got %d byte response %s", rc, responseline);
+
+		enum response_state {
+			RESPONSE_CHAR,
+			RESPONSE_CR,
+			RESPONSE_CRLF,
+			RESPONSE_CRLFCR,
+			RESPONSE_END_OF_HEADERS /* saw crlfcrlf */
+		} response_state = RESPONSE_CHAR;
+		while (response_state != RESPONSE_END_OF_HEADERS) {
+			guchar ch;
+			if (gst_tcp_socket_read (src->sock_fd, (guchar *)&ch, sizeof(ch)) <= 0) {
+				GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
+				 ("reading HTTP response from %s failed: %s", src->daap_uri,
+					g_strerror (errno)));
+				return FALSE;
+			}
+			switch (ch) {
+				case '\n':
+					switch (response_state) {
+						case RESPONSE_CR: 
+							response_state = RESPONSE_CRLF; 
+							break;
+						case RESPONSE_CRLFCR: 
+							response_state = RESPONSE_END_OF_HEADERS; 
+							break;
+						default: 
+							response_state = RESPONSE_CHAR;
+							break;
+					} 
+					break;	
+				case '\r':
+					switch (response_state) {
+						case RESPONSE_CRLF: 
+							response_state = RESPONSE_CRLFCR; 
+							break;
+						default: 
+							response_state = RESPONSE_CR;
+							break;
+					}
+					break;
+				default:
+					response_state = RESPONSE_CHAR;
+			}
+		}
+	}
+	
+	return TRUE;
+}
+
+static gboolean
+rb_daap_src_stop (GstBaseSrc *bsrc)
+{
+	/*RBDAAPSrc *src = RB_DAAP_SRC (bsrc);*/
+
+	/* We don't really want to do this, since we seem to be stopped during
+	 * setup, and not started again, so we wind up trying to read without a
+	 * connection.  playbin recreates the source element for each song
+	 * anyway.
+	 */
+	/*
+	if (src->sock_fd != -1) {
+		close (src->sock_fd);
+		src->sock_fd = -1;
+	}
+	src->curoffset = 0;
+	src->seek_bytes = 0;
+	src->seek_time = 0;
+	src->do_seek = FALSE;
+	*/
+	return FALSE;
+}
+
+static GstFlowReturn
+rb_daap_src_create (GstPushSrc *psrc, GstBuffer **outbuf)
+{
+	RBDAAPSrc *src;
+	GstBuffer *buf;
+	glong readbytes;
+	guint blocksize;
+
+	src = RB_DAAP_SRC (psrc);
+
+	if (src->do_seek) {
+		if (src->sock_fd != -1) {
+			close (src->sock_fd);
+			src->sock_fd = -1;
+		}
+		rb_daap_src_start (GST_BASE_SRC (psrc));
+	}
+
+	blocksize = GST_BASE_SRC (src)->blocksize;
+	
+	buf = gst_buffer_new_and_alloc (blocksize);
+
+	readbytes = gst_tcp_socket_read (src->sock_fd, GST_BUFFER_DATA (buf), blocksize);
+	if (readbytes < 0) {
+		GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
+			("reading from daap server: %s.", g_strerror (errno)));
+		GST_DEBUG_OBJECT (src, "Error reading from daap server");
+		gst_buffer_unref (buf);
+		return GST_FLOW_ERROR;
+	}
+	if (readbytes == 0) {
+		GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), ("unexpected end of file."));
+		gst_buffer_unref (buf);
+		return GST_FLOW_UNEXPECTED;
+	}
+
+	GST_BUFFER_OFFSET (buf) = src->curoffset;
+	GST_BUFFER_SIZE (buf) = readbytes;
+	GST_BUFFER_TIMESTAMP (buf) = GST_CLOCK_TIME_NONE;
+		
+	src->curoffset += readbytes;
+
+	*outbuf = buf;
+	return GST_FLOW_OK;
+}
+
+gboolean
+rb_daap_src_is_seekable (GstBaseSrc *bsrc)
+{
+	return FALSE;
+}
+
+gboolean
+rb_daap_src_get_size (GstBaseSrc *bsrc, guint64 *size)
+{
+	/* we could pull this out of the response headers, if we were smart enough.. */
+	return FALSE;
+}
+
+
+static gboolean
+plugin_init (GstPlugin *plugin)
+{
+	gboolean ret = gst_element_register (plugin, "rbdaapsrc", GST_RANK_PRIMARY, RB_TYPE_DAAP_SRC);
+
+	return ret;
+}
+
+GST_PLUGIN_DEFINE_STATIC (GST_VERSION_MAJOR,
+			  GST_VERSION_MINOR,
+			  "rbdaap",
+			  "element to access DAAP music share files",
+			  plugin_init,
+			  VERSION,
+			  "GPL",
+			  PACKAGE,
+			  "");
+
+/*** RB DAAP SEEK INTERFACE **************************************************/
+
+void
+rb_daap_src_set_time (GstElement *element, glong time)
+{
+	RBDAAPSrc *src = RB_DAAP_SRC (element);
+	src->seek_time = time;
+	src->do_seek = TRUE;
+}
+
+glong
+rb_daap_src_get_time (GstElement *element)
+{
+	RBDAAPSrc *src = RB_DAAP_SRC (element);
+	return src->seek_time;
+}
+
+/*** GSTURIHANDLER INTERFACE *************************************************/
+
+static guint
+rb_daap_src_uri_get_type (void)
+{
+	return GST_URI_SRC;
+}
+
+static gchar **
+rb_daap_src_uri_get_protocols (void)
+{
+	static gchar *protocols[] = {"daap", NULL};
+
+	return protocols;
+}
+
+static const gchar *
+rb_daap_src_uri_get_uri (GstURIHandler *handler)
+{
+	RBDAAPSrc *src = RB_DAAP_SRC (handler);
+
+	return src->daap_uri;
+}
+
+static gboolean
+rb_daap_src_uri_set_uri (GstURIHandler *handler, 
+			 const gchar *uri)
+{
+	RBDAAPSrc *src = RB_DAAP_SRC (handler);
+
+	if (GST_STATE (src) == GST_STATE_PLAYING || GST_STATE (src) == GST_STATE_PAUSED) {
+		return FALSE;
+	}
+
+	g_object_set (G_OBJECT (src), "location", uri, NULL);
+
+	return TRUE;
+}
+
+
+static void 
+rb_daap_src_uri_handler_init (gpointer g_iface, 
+			      gpointer iface_data)
+{
+	GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
+
+	iface->get_type = rb_daap_src_uri_get_type;
+	iface->get_protocols = rb_daap_src_uri_get_protocols;
+	iface->get_uri = rb_daap_src_uri_get_uri;
+	iface->set_uri = rb_daap_src_uri_set_uri;
+}
+
