diff -rN -u -p old-daap/backends/gstreamer/Makefile.am new-daap/backends/gstreamer/Makefile.am
--- old-daap/backends/gstreamer/Makefile.am	2006-11-04 20:39:02.000000000 +1000
+++ new-daap/backends/gstreamer/Makefile.am	2006-11-04 20:39:04.000000000 +1000
@@ -30,7 +30,3 @@ librbbackendsgstreamer_la_SOURCES +=	\
 	rb-encoder-gst.c
 endif
 
-if USE_DAAP
-INCLUDES += -I$(top_srcdir)/daapsharing			
-endif
-
diff -rN -u -p old-daap/backends/gstreamer/rb-player-gst.c new-daap/backends/gstreamer/rb-player-gst.c
--- old-daap/backends/gstreamer/rb-player-gst.c	2006-11-04 20:39:02.000000000 +1000
+++ new-daap/backends/gstreamer/rb-player-gst.c	2006-11-04 20:39:04.000000000 +1000
@@ -41,10 +41,6 @@
 #include "rb-debug.h"
 #include "rb-marshal.h"
 
-#if defined(HAVE_GSTREAMER_0_8) && defined(WITH_DAAP_SUPPORT)
-#include "rb-daap-src.h"
-#endif
-
 static void rb_player_init (RBPlayerIface *iface);
 static void rb_player_gst_finalize (GObject *object);
 
@@ -1053,24 +1049,6 @@ rb_player_gst_set_time (RBPlayer *player
 	}
 #endif
 
-#if defined(HAVE_GSTREAMER_0_8) && defined(WITH_DAAP_SUPPORT)
-	/* FIXME?
-	 * This is sorta hack/sorta best way to do it.
-	 * If we set up the daapsrc to do regular GStreamer seeking,
-	 * GStreamer goes ape-shit and tries to seek all over the
-	 * place (typefinding), which can cause iTunes to return errors
-	 * (probably cause we're requesting the same file too often)
- 	 *
-	 * So, we do it this way.  Doesn't that suck?
-	 */
-	if (mp->priv->uri && g_strncasecmp (mp->priv->uri, "daap://", 7) == 0) {
-		GstElement *src;
-
-		g_object_get (G_OBJECT (mp->priv->playbin), "source", &src, NULL);
-		if (src)
-			rb_daap_src_set_time (src, time);
-	} else {
-#endif
 #ifdef HAVE_GSTREAMER_0_8
 	gst_element_seek (mp->priv->playbin,
 			  GST_FORMAT_TIME
@@ -1084,9 +1062,6 @@ rb_player_gst_set_time (RBPlayer *player
 			  GST_SEEK_TYPE_NONE, -1);
 #endif
 
-#if defined(HAVE_GSTREAMER_0_8) && defined(WITH_DAAP_SUPPORT)
-	}
-#endif
 	if (mp->priv->playing) {
 		gst_element_set_state (mp->priv->playbin, GST_STATE_PLAYING);
 	}
@@ -1109,15 +1084,6 @@ rb_player_gst_get_time (RBPlayer *player
 		if (position != -1)
 			position /= GST_SECOND;
 
-#if defined(HAVE_GSTREAMER_0_8) && defined(WITH_DAAP_SUPPORT)
-		if (mp->priv->uri && g_strncasecmp (mp->priv->uri, "daap://", 7) == 0) {
-			GstElement *src;
-			g_object_get (G_OBJECT (mp->priv->playbin), "source", &src, NULL);
-			if (src)
-				position += rb_daap_src_get_time (src);
-		}
-#endif
-
 		return (long) position;
 	} else
 		return -1;
diff -rN -u -p old-daap/configure.ac new-daap/configure.ac
--- old-daap/configure.ac	2006-11-04 20:39:02.000000000 +1000
+++ new-daap/configure.ac	2006-11-04 20:39:03.000000000 +1000
@@ -40,7 +40,7 @@ if test x"$have_fwrite_unlocked" = xyes;
 	AC_MSG_RESULT([yes])
 else
 	AC_MSG_RESULT([no])
-fi	
+fi
 
 mkdtemp_missing=false
 AC_CHECK_FUNC(mkdtemp,
@@ -67,7 +67,7 @@ PKG_CHECK_MODULES(RHYTHMBOX,				\
 PKG_CHECK_MODULES(TOTEM_PLPARSER, totem-plparser >= $TOTEM_PLPARSER_REQS, have_totem_plparser=yes, have_totem_plparser=no)
 if test x$have_totem_plparser != xyes; then
    AC_MSG_ERROR([totem playlist parsing library not found or too old])
-fi   
+fi
 
 AC_ARG_WITH(hal,
 	      AC_HELP_STRING([--without-hal],
@@ -111,7 +111,7 @@ if test "x$with_ipod" != "xno"; then
 	fi
 	if test "x$have_libgpod" = "xyes"; then
           if test "x$with_hal" = xyes && test "x$enable_hal" = xno; then
-	     AC_MSG_ERROR([iPod explicitly requested but HAL not found or too old])	   
+	     AC_MSG_ERROR([iPod explicitly requested but HAL not found or too old])
 	  fi
           if test "x$enable_hal" = xyes; then
 	     AC_DEFINE(WITH_IPOD_SUPPORT, 1, [Define if iPod support is enabled])
@@ -120,7 +120,7 @@ if test "x$with_ipod" != "xno"; then
 	  AC_SUBST(IPOD_CFLAGS)
 	  AC_SUBST(IPOD_LIBS)
 	fi
-fi			  
+fi
 AM_CONDITIONAL(USE_IPOD, test x"$use_ipod" = xyes)
 
 
@@ -142,7 +142,7 @@ if test "x$with_gnome_keyring" != "xno";
 	  AC_SUBST(GNOME_KEYRING_CFLAGS)
 	  AC_SUBST(GNOME_KEYRING_LIBS)
 	fi
-fi			  
+fi
 AM_CONDITIONAL(USE_GNOME_KEYRING, test x"$use_gnome_keyring" = xyes)
 
 dnl Database
@@ -191,7 +191,7 @@ PKG_CHECK_MODULES(GSTREAMER_0_8, \
 	gstreamer-control-$GST_0_8_MAJORMINOR >= $GST_0_8_REQUIRED_VERSION
 	gstreamer-gconf-$GST_0_8_MAJORMINOR >= $GST_0_8_REQUIRED_VERSION,
 	have_gstreamer_0_8=yes,have_gstreamer_0_8=no)
-	
+
 GST_0_10_MAJORMINOR=0.10
 GST_0_10_REQUIRED_VERSION=0.9.7
 PKG_CHECK_MODULES(GSTREAMER_0_10, \
@@ -256,7 +256,7 @@ AC_ARG_ENABLE(track-transfer,
 			     [Disable track transfer support in rhythmbox]))
 if test x"$enable_track_transfer" != xno; then
    PKG_CHECK_MODULES(GNOME_MEDIA_PROFILES,
-      gnome-media-profiles >= 2.8, 
+      gnome-media-profiles >= 2.8,
       with_track_transfer=yes,
       with_track_transfer=no)
 
@@ -412,7 +412,7 @@ if test "x$enable_libnotify" != "xno"; t
 	if test "x$have_libnotify" = "xyes"; then
 	     enable_libnotify=yes
 	fi
-fi			  
+fi
 AM_CONDITIONAL(USE_NOTIFY, test x"$enable_libnotify" = xyes)
 if test x$enable_libnotify = xyes ; then
     # Find out the version of LIBNOTIFY we're using
@@ -485,6 +485,11 @@ if test "x$enable_daap" != "xno"; then
 			AC_MSG_ERROR([DAAP support explicitly requested, but no mDNS implementation found.  Install Howl or Avahi])
 		fi
 		enable_daap=no
+	elif test x"$with_playback" = xgstreamer_0_8; then
+		if test "x$enable_daap" = "xyes"; then
+			AC_MSG_ERROR([DAAP support explicitly requested, but not supported with GStreamer 0.8])
+		fi
+		enable_daap=no
 	else
 		AC_DEFINE(WITH_DAAP_SUPPORT, 1, [Define if DAAP should be enabled])
 		enable_daap="yes"
@@ -643,9 +648,9 @@ if test "x$enable_dbus" = xno; then
    if test "x$enable_old_dbus" = xno; then
       AC_MSG_ERROR([DBUS not found or too old])
    fi
-   AC_DEFINE(WITH_OLD_DBUS, 1, [Define if old D-BUS is enabled])	   
+   AC_DEFINE(WITH_OLD_DBUS, 1, [Define if old D-BUS is enabled])
 else
-   AC_DEFINE(WITH_DBUS, 1, [Define if D-BUS is enabled])	   
+   AC_DEFINE(WITH_DBUS, 1, [Define if D-BUS is enabled])
 fi
 
 DBUS_CFLAGS="$DBUS_CFLAGS -DDBUS_API_SUBJECT_TO_CHANGE"
@@ -915,7 +920,7 @@ dnl ====================================
 dnl end-game
 dnl ================================================================
 
-AC_OUTPUT([ 
+AC_OUTPUT([
 Makefile
 macros/Makefile
 lib/Makefile
@@ -937,6 +942,7 @@ plugins/sample/Makefile
 plugins/audiocd/Makefile
 plugins/audioscrobbler/Makefile
 plugins/cd-recorder/Makefile
+plugins/daap/Makefile
 plugins/ipod/Makefile
 plugins/iradio/Makefile
 plugins/lirc/Makefile
diff -rN -u -p old-daap/CVS-SURGERY new-daap/CVS-SURGERY
--- old-daap/CVS-SURGERY	2006-11-04 20:39:02.000000000 +1000
+++ new-daap/CVS-SURGERY	2006-11-04 20:39:04.000000000 +1000
@@ -27,4 +27,9 @@ CVS surgery patient waiting list:
  iradio/rb-station-properties-dialog.h -> plugins/iradio/
  iradio/rb-station-properties-dialog.c -> plugins/iradio/
 
-
+ sources/rb-daap-source.c -> plugins/daap/
+ sources/rb-daap-source.h -> plugins/daap/
+ data/ui/daap-ui.xml -> plugins/daap/
+ data/glade/daap-prefs.glade -> plugins/daap/
+ daapsharing/* -> plugins/daap/
+ (possibly with the exception of the mdns stuff?)
diff -rN -u -p old-daap/daapsharing/Makefile.am new-daap/daapsharing/Makefile.am
--- old-daap/daapsharing/Makefile.am	2006-11-04 20:39:01.000000000 +1000
+++ new-daap/daapsharing/Makefile.am	2006-11-04 20:39:02.000000000 +1000
@@ -44,14 +44,14 @@ INCLUDES =						\
 	-I$(top_srcdir) 				\
 	-I$(top_srcdir)/lib 				\
 	-I$(top_builddir)/lib 				\
-	-I$(top_srcdir)/corba 				\
-	-I$(top_builddir)/corba				\
 	-I$(top_srcdir)/rhythmdb			\
 	-I$(top_srcdir)/library 			\
 	-I$(top_srcdir)/iradio				\
 	-I$(top_srcdir)/widgets				\
 	-I$(top_srcdir)/shell				\
 	-I$(top_srcdir)/sources				\
+	-I$(top_srcdir)/plugins				\
+	-I$(top_srcdir)/plugins/daap			\
 	-DPIXMAP_DIR=\""$(datadir)/pixmaps"\"		\
 	-DSHARE_DIR=\"$(pkgdatadir)\"                   \
 	-DDATADIR=\""$(datadir)"\"			\
diff -rN -u -p old-daap/daapsharing/rb-daap-connection.c new-daap/daapsharing/rb-daap-connection.c
--- old-daap/daapsharing/rb-daap-connection.c	2006-11-04 20:39:01.000000000 +1000
+++ new-daap/daapsharing/rb-daap-connection.c	2006-11-04 20:39:02.000000000 +1000
@@ -1371,7 +1371,9 @@ rb_daap_connection_disconnect (RBDAAPCon
 		   hasn't returned yet so we need to force the connection
 		   to finish */
 		priv->state = DAAP_DONE;
+		GDK_THREADS_LEAVE ();
 		rb_daap_connection_finish (connection);
+		GDK_THREADS_ENTER ();
 	}
 
 	rdata = g_new (ConnectionResponseData, 1);
@@ -1388,7 +1390,9 @@ rb_daap_connection_disconnect (RBDAAPCon
 
 	if (! connection->priv->is_connected) {
 		priv->state = DAAP_DONE;
+		GDK_THREADS_LEAVE ();
 		rb_daap_connection_finish (connection);
+		GDK_THREADS_ENTER ();
 	} else {
 		priv->state = DAAP_LOGOUT;
 
diff -rN -u -p old-daap/daapsharing/rb-daap-src.c new-daap/daapsharing/rb-daap-src.c
--- old-daap/daapsharing/rb-daap-src.c	2006-11-04 20:39:01.000000000 +1000
+++ new-daap/daapsharing/rb-daap-src.c	2006-11-04 20:39:02.000000000 +1000
@@ -47,6 +47,7 @@
 #include "rb-daap-source.h"
 #include "rb-daap-src.h"
 #include "rb-debug.h"
+#include "rb-daap-plugin.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))
@@ -127,6 +128,8 @@ GST_ELEMENT_DETAILS ("RBDAAP Source",
 	"Read a DAAP (music share) file",
 	"Charles Schmidt <cschmidt2@emich.edu");
 
+static RBDaapPlugin *daap_plugin = NULL;
+
 static void rb_daap_src_uri_handler_init (gpointer g_iface, gpointer iface_data);
 
 static void
@@ -183,6 +186,13 @@ static gboolean rb_daap_src_do_seek (Gst
 static GstFlowReturn rb_daap_src_create (GstPushSrc *psrc, GstBuffer **outbuf);
 #endif
 
+void
+rb_daap_src_set_plugin (RBPlugin *plugin)
+{
+	g_assert (RB_IS_DAAP_PLUGIN (plugin));
+	daap_plugin = RB_DAAP_PLUGIN (plugin);
+}
+
 #ifdef HAVE_GSTREAMER_0_8
 
 static const GstFormat *
@@ -635,7 +645,7 @@ rb_daap_src_open (RBDAAPSrc *src)
 	}
 
 	/* construct request */
-	source = rb_daap_source_find_for_uri (src->daap_uri);
+	source = rb_daap_plugin_find_source_for_uri (daap_plugin, src->daap_uri);
 	if (source == NULL) {
 		g_warning ("Unable to lookup source for URI: %s", src->daap_uri);
 		return FALSE;
diff -rN -u -p old-daap/daapsharing/rb-daap-src.h new-daap/daapsharing/rb-daap-src.h
--- old-daap/daapsharing/rb-daap-src.h	2006-11-04 20:39:01.000000000 +1000
+++ new-daap/daapsharing/rb-daap-src.h	2006-11-04 20:39:02.000000000 +1000
@@ -28,9 +28,12 @@
 G_BEGIN_DECLS
 
 GType rb_daap_src_get_type (void);
+void rb_daap_src_set_plugin (RBPlugin *plugin);
 
+#ifdef HAVE_GSTREAMER_0_8
 void rb_daap_src_set_time (GstElement *element, glong time);
 glong rb_daap_src_get_time (GstElement *element);
+#endif
 
 G_END_DECLS
 
diff -rN -u -p old-daap/data/glade/Makefile.am new-daap/data/glade/Makefile.am
--- old-daap/data/glade/Makefile.am	2006-11-04 20:39:01.000000000 +1000
+++ new-daap/data/glade/Makefile.am	2006-11-04 20:39:02.000000000 +1000
@@ -13,7 +13,6 @@ glade_DATA =	general-prefs.glade	  	\
 		create-playlist.glade		\
 		druid.glade			\
 		recorder.glade			\
-		daap-prefs.glade		\
 		uri.glade			\
 		plugins.glade			\
 		audioscrobbler-prefs.glade	\
diff -rN -u -p old-daap/data/rhythmbox.schemas new-daap/data/rhythmbox.schemas
--- old-daap/data/rhythmbox.schemas	2006-11-04 20:39:01.000000000 +1000
+++ new-daap/data/rhythmbox.schemas	2006-11-04 20:39:02.000000000 +1000
@@ -1011,5 +1011,27 @@
 	<long>The size of the browser.</long>
         </locale>
       </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/plugins/daap/active</key>
+        <applyto>/apps/rhythmbox/plugins/daap/active</applyto>
+        <owner>rhythmbox</owner>
+        <type>bool</type>
+        <default>TRUE</default>
+        <locale name="C">
+        <short>True if the DAAP plugin is enabled.</short>
+	<long>True if the DAAP plugin is enabled.</long>
+	</locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/plugins/daap/hidden</key>
+        <applyto>/apps/rhythmbox/plugins/daap/hidden</applyto>
+        <owner>rhythmbox</owner>
+        <type>bool</type>
+        <default>FALSE</default>
+        <locale name="C">
+        <short>True if the DAAP plugin is hidden.</short>
+	<long>True if the DAAP plugin is hidden.</long>
+	</locale>
+      </schema>
     </schemalist>
 </gconfschemafile>
diff -rN -u -p old-daap/data/ui/Makefile.am new-daap/data/ui/Makefile.am
--- old-daap/data/ui/Makefile.am	2006-11-04 20:39:01.000000000 +1000
+++ new-daap/data/ui/Makefile.am	2006-11-04 20:39:02.000000000 +1000
@@ -1,7 +1,7 @@
 ## arch-tag: Automake rules for XML user interface definition stuff
 
 uixmldir = $(pkgdatadir)
-uixml_DATA = rhythmbox-ui.xml ipod-ui.xml daap-ui.xml generic-player-ui.xml
+uixml_DATA = rhythmbox-ui.xml ipod-ui.xml generic-player-ui.xml
 
-EXTRA_DIST = rhythmbox-ui.xml ipod-ui.xml daap-ui.xml generic-player-ui.xml
+EXTRA_DIST = rhythmbox-ui.xml ipod-ui.xml generic-player-ui.xml
 
diff -rN -u -p old-daap/plugins/daap/.cvsignore new-daap/plugins/daap/.cvsignore
--- old-daap/plugins/daap/.cvsignore	1970-01-01 10:00:00.000000000 +1000
+++ new-daap/plugins/daap/.cvsignore	2006-11-04 20:39:03.000000000 +1000
@@ -0,0 +1,3 @@
+Makefile
+Makefile.in
+daap.rb-plugin
diff -rN -u -p old-daap/plugins/daap/daap.rb-plugin.desktop.in new-daap/plugins/daap/daap.rb-plugin.desktop.in
--- old-daap/plugins/daap/daap.rb-plugin.desktop.in	1970-01-01 10:00:00.000000000 +1000
+++ new-daap/plugins/daap/daap.rb-plugin.desktop.in	2006-11-04 20:39:03.000000000 +1000
@@ -0,0 +1,8 @@
+[RB Plugin]
+Module=daap
+IAge=1
+_Name=DAAP Music Sharing
+_Description=Share music and play shared music on your local network
+Authors=Charles Schmidt  <cschmidt2@emich.edu>, the Rhythmbox Developers
+Copyright=Copyright © 2005-2006 Charles Schmidt, the Rhythmbox Developers
+Website=http://www.rhythmbox.org
diff -rN -u -p old-daap/plugins/daap/Makefile.am new-daap/plugins/daap/Makefile.am
--- old-daap/plugins/daap/Makefile.am	1970-01-01 10:00:00.000000000 +1000
+++ new-daap/plugins/daap/Makefile.am	2006-11-04 20:39:03.000000000 +1000
@@ -0,0 +1,78 @@
+NULL =
+
+plugindir = $(PLUGINDIR)/daap
+plugin_LTLIBRARIES = libdaap.la
+
+libdaap_la_SOURCES = \
+	rb-daap-plugin.c			\
+	$(top_srcdir)/sources/rb-daap-source.c	\
+	$(top_srcdir)/sources/rb-daap-source.h
+
+libdaap_la_LDFLAGS = $(PLUGIN_LIBTOOL_FLAGS)
+libdaap_la_LIBADD = 				\
+	$(top_builddir)/lib/librb.la			\
+	$(top_builddir)/daapsharing/libdaapsharing.la	\
+	$(SOUP_LIBS)					\
+	$(MDNS_LIBS)
+
+INCLUDES = 						\
+        -DGNOMELOCALEDIR=\""$(datadir)/locale"\"        \
+	-DG_LOG_DOMAIN=\"Rhythmbox\"		 	\
+	-I$(top_srcdir) 				\
+	-I$(top_srcdir)/lib                        	\
+	-I$(top_srcdir)/metadata                       	\
+	-I$(top_srcdir)/player                       	\
+	-I$(top_srcdir)/rhythmdb                       	\
+	-I$(top_srcdir)/widgets                    	\
+	-I$(top_srcdir)/sources                    	\
+	-I$(top_srcdir)/iradio                    	\
+	-I$(top_srcdir)/podcast                    	\
+	-I$(top_srcdir)/remote				\
+	-I$(top_builddir)/remote			\
+	-I$(top_srcdir)/plugins				\
+	-I$(top_srcdir)/shell				\
+	-I$(top_srcdir)/daapsharing			\
+	-I$(top_srcdir)/plugins				\
+	-DPIXMAP_DIR=\""$(datadir)/pixmaps"\"		\
+	-DSHARE_DIR=\"$(pkgdatadir)\"                   \
+	-DDATADIR=\""$(datadir)"\"			\
+	$(SOUP_CFLAGS)					\
+	$(MDNS_CFLAGS)					\
+	$(RHYTHMBOX_CFLAGS)				\
+	$(WARN_CFLAGS)					\
+	-D_XOPEN_SOURCE -D_BSD_SOURCE
+
+if USE_GNOME_KEYRING
+libdaap_la_LIBADD += $(GNOME_KEYRING_LIBS)
+INCLUDES += $(GNOME_KEYRING_CFLAGS)
+endif
+
+gladedir = $(datadir)/rhythmbox/glade
+glade_DATA = ../../data/glade/daap-prefs.glade
+
+plugin_in_files = daap.rb-plugin.desktop.in
+
+%.rb-plugin: %.rb-plugin.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache
+
+BUILT_SOURCES =							\
+	$(plugin_in_files:.rb-plugin.desktop.in=.rb-plugin) 	\
+	$(NULL)
+
+plugin_DATA = 			\
+	$(BUILT_SOURCES)	\
+	$(NULL)
+
+EXTRA_DIST = 			\
+	$(glade_DATA)		\
+	$(plugin_in_files)	\
+	../../data/ui/daap-ui.xml \
+	$(NULL)
+
+CLEANFILES = 			\
+	$(BUILT_SOURCES)	\
+	$(NULL)
+
+DISTCLEANFILES =		\
+	$(BUILT_SOURCES)	\
+	$(NULL)
+
diff -rN -u -p old-daap/plugins/daap/rb-daap-plugin.c new-daap/plugins/daap/rb-daap-plugin.c
--- old-daap/plugins/daap/rb-daap-plugin.c	1970-01-01 10:00:00.000000000 +1000
+++ new-daap/plugins/daap/rb-daap-plugin.c	2006-11-04 20:39:03.000000000 +1000
@@ -0,0 +1,797 @@
+/*
+ * rb-daap-plugin.c
+ *
+ * Copyright (C) 2006 James Livingston <jrl@ids.org.au>
+ *
+ * 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, 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <glib/gi18n-lib.h>
+#include <gmodule.h>
+#include <gtk/gtk.h>
+#include <glib.h>
+#include <glib-object.h>
+
+#include "rb-daap-plugin.h"
+#include "rb-debug.h"
+#include "rb-shell.h"
+#include "rb-dialog.h"
+#include "rb-file-helpers.h"
+#include "rb-glade-helpers.h"
+#include "eel-gconf-extensions.h"
+#include "rb-daap-source.h"
+#include "rb-daap-sharing.h"
+#include "rb-daap-src.h"
+
+#include "rb-daap-mdns-browser.h"
+
+/* preferences */
+#define CONF_DAAP_PREFIX  	CONF_PREFIX "/plugins/daap"
+#define CONF_ENABLE_BROWSING 	CONF_DAAP_PREFIX "/enable_browsing"
+
+struct RBDaapPluginPrivate
+{
+	RBShell *shell;
+
+	GtkWidget *preferences;
+	gboolean sharing;
+	gboolean shutdown;
+
+	GtkActionGroup *daap_action_group;
+	guint daap_ui_merge_id;
+
+	RBDaapMdnsBrowser *mdns_browser;
+
+	GHashTable *source_lookup;
+
+	guint enable_browsing_notify_id;
+
+	GdkPixbuf *daap_share_pixbuf;
+	GdkPixbuf *daap_share_locked_pixbuf;
+};
+
+enum
+{
+	PROP_0,
+	PROP_SHUTDOWN
+};
+
+G_MODULE_EXPORT GType register_rb_plugin (GTypeModule *module);
+
+static void rb_daap_plugin_get_property (GObject *object,
+					 guint prop_id,
+					 GValue *value,
+					 GParamSpec *pspec);
+
+static void rb_daap_plugin_init (RBDaapPlugin *plugin);
+static void rb_daap_plugin_finalize (GObject *object);
+static void impl_activate (RBPlugin *plugin, RBShell *shell);
+static void impl_deactivate (RBPlugin *plugin, RBShell *shell);
+
+static GtkWidget* impl_create_configure_dialog (RBPlugin *plugin);
+static void rb_daap_plugin_cmd_disconnect (GtkAction *action, RBDaapPlugin *plugin);
+
+static void create_pixbufs (RBDaapPlugin *plugin);
+static void start_browsing (RBDaapPlugin *plugin);
+static void stop_browsing (RBDaapPlugin *plugin);
+static void enable_browsing_changed_cb (GConfClient *client,
+					guint cnxn_id,
+					GConfEntry *entry,
+					RBDaapPlugin *plugin);
+
+RB_PLUGIN_REGISTER(RBDaapPlugin, rb_daap_plugin)
+
+static GtkActionEntry rb_daap_source_actions [] =
+{
+	{ "DaapSourceDisconnect", GTK_STOCK_DISCONNECT, N_("_Disconnect"), NULL,
+	  N_("Disconnect from DAAP share"),
+	  G_CALLBACK (rb_daap_plugin_cmd_disconnect) },
+};
+
+static void
+rb_daap_plugin_cmd_disconnect (GtkAction *action,
+			       RBDaapPlugin *plugin)
+{
+	RBSource *source;
+
+	g_object_get (plugin->priv->shell,
+		      "selected-source", &source,
+		      NULL);
+
+	if (!RB_IS_DAAP_SOURCE (source)) {
+		g_critical ("got non-Daap source for Daap action");
+		return;
+	}
+
+	rb_daap_source_disconnect (RB_DAAP_SOURCE (source));
+
+	if (source != NULL) {
+		g_object_unref (source);
+	}
+}
+
+
+static void
+rb_daap_plugin_class_init (RBDaapPluginClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	RBPluginClass *plugin_class = RB_PLUGIN_CLASS (klass);
+
+	object_class->finalize = rb_daap_plugin_finalize;
+	object_class->get_property = rb_daap_plugin_get_property;
+
+	plugin_class->activate = impl_activate;
+	plugin_class->deactivate = impl_deactivate;
+	plugin_class->create_configure_dialog = impl_create_configure_dialog;
+
+	g_object_class_install_property (object_class,
+					 PROP_SHUTDOWN,
+					 g_param_spec_boolean ("shutdown",
+							       "shutdown",
+							       "Whether the DAAP plugin has been shut down",
+							       FALSE,
+							       G_PARAM_READABLE));
+
+	g_type_class_add_private (object_class, sizeof (RBDaapPluginPrivate));
+}
+
+static void
+rb_daap_plugin_init (RBDaapPlugin *plugin)
+{
+	rb_debug ("RBDaapPlugin initialising");
+	plugin->priv = G_TYPE_INSTANCE_GET_PRIVATE (plugin, RB_TYPE_DAAP_PLUGIN, RBDaapPluginPrivate);
+
+	rb_daap_src_set_plugin (RB_PLUGIN (plugin));
+}
+
+static void
+rb_daap_plugin_finalize (GObject *object)
+{
+	RBDaapPlugin *plugin = RB_DAAP_PLUGIN (object);
+
+	rb_debug ("RBDaapPlugin finalising");
+
+	if (plugin->priv->preferences)
+		gtk_widget_destroy (plugin->priv->preferences);
+
+	G_OBJECT_CLASS (rb_daap_plugin_parent_class)->finalize (object);
+}
+
+
+static void
+rb_daap_plugin_get_property (GObject *object,
+			     guint prop_id,
+			     GValue *value,
+			     GParamSpec *pspec)
+{
+	RBDaapPlugin *plugin = RB_DAAP_PLUGIN (object);
+
+	switch (prop_id) {
+	case PROP_SHUTDOWN:
+		g_value_set_boolean (value, plugin->priv->shutdown);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+impl_activate (RBPlugin *bplugin,
+	       RBShell *shell)
+{
+	RBDaapPlugin *plugin = RB_DAAP_PLUGIN (bplugin);
+	gboolean no_registration;
+	gboolean enabled = TRUE;
+	GConfValue *value;
+	GConfClient *client = eel_gconf_client_get_global ();
+	GtkUIManager *uimanager = NULL;
+	char *uifile;
+
+	plugin->priv->shell = g_object_ref (shell);
+
+	value = gconf_client_get_without_default (client,
+						  CONF_ENABLE_BROWSING, NULL);
+	if (value != NULL) {
+		enabled = gconf_value_get_bool (value);
+		gconf_value_free (value);
+	}
+
+	if (enabled) {
+		start_browsing (plugin);
+	}
+
+	plugin->priv->enable_browsing_notify_id =
+		eel_gconf_notification_add (CONF_ENABLE_BROWSING,
+					    (GConfClientNotifyFunc) enable_browsing_changed_cb,
+					    plugin);
+
+	create_pixbufs (plugin);
+
+	g_object_get (shell,
+		      "ui-manager", &uimanager,
+		      NULL);
+
+	/* add actions */
+	plugin->priv->daap_action_group = gtk_action_group_new ("DaapActions");
+	gtk_action_group_set_translation_domain (plugin->priv->daap_action_group,
+						 GETTEXT_PACKAGE);
+	gtk_action_group_add_actions (plugin->priv->daap_action_group,
+				      rb_daap_source_actions, G_N_ELEMENTS (rb_daap_source_actions),
+				      plugin);
+	gtk_ui_manager_insert_action_group (uimanager, plugin->priv->daap_action_group, 0);
+
+	/* add UI */
+	uifile = rb_plugin_find_file (bplugin, "daap-ui.xml");
+	if (uifile == NULL) {
+		uifile = g_strdup (rb_file ("daap-ui.xml"));
+	}
+
+	if (uifile != NULL) {
+		plugin->priv->daap_ui_merge_id = gtk_ui_manager_add_ui_from_file (uimanager, uifile, NULL);
+		g_free (uifile);
+	}
+
+	g_object_unref (uimanager);
+
+	/*
+	 * Don't use daap when the no-registration flag is set.
+	 * This flag is only used to run multiple instances at the same time, and
+	 * sharing from two instances would be silly
+	 */
+	g_object_get (G_OBJECT (shell),
+		      "no-registration", &no_registration,
+		      NULL);
+	plugin->priv->sharing = !no_registration;
+	if (plugin->priv->sharing)
+		rb_daap_sharing_init (shell);
+}
+
+static void
+impl_deactivate	(RBPlugin *bplugin,
+		 RBShell *shell)
+{
+	RBDaapPlugin *plugin = RB_DAAP_PLUGIN (bplugin);
+	GtkUIManager *uimanager = NULL;
+
+	rb_debug ("Shutting down DAAP plugin");
+
+	plugin->priv->shutdown = TRUE;
+
+	if (plugin->priv->sharing)
+		rb_daap_sharing_shutdown (shell);
+
+	if (plugin->priv->mdns_browser) {
+		stop_browsing (plugin);
+	}
+
+	if (plugin->priv->enable_browsing_notify_id != EEL_GCONF_UNDEFINED_CONNECTION) {
+		eel_gconf_notification_remove (plugin->priv->enable_browsing_notify_id);
+		plugin->priv->enable_browsing_notify_id = EEL_GCONF_UNDEFINED_CONNECTION;
+	}
+
+	g_object_get (shell,
+		      "ui-manager", &uimanager,
+		      NULL);
+
+	gtk_ui_manager_remove_ui (uimanager, plugin->priv->daap_ui_merge_id);
+	gtk_ui_manager_remove_action_group (uimanager, plugin->priv->daap_action_group);
+
+	g_object_unref (uimanager);
+
+	if (plugin->priv->daap_share_pixbuf != NULL) {
+		g_object_unref (plugin->priv->daap_share_pixbuf);
+		plugin->priv->daap_share_pixbuf = NULL;
+	}
+
+	if (plugin->priv->daap_share_locked_pixbuf != NULL) {
+		g_object_unref (plugin->priv->daap_share_locked_pixbuf);
+		plugin->priv->daap_share_locked_pixbuf = NULL;
+	}
+
+	if (plugin->priv->shell) {
+		g_object_unref (plugin->priv->shell);
+		plugin->priv->shell = NULL;
+	}
+}
+
+/* DAAP share icons */
+
+static GdkPixbuf *
+composite_icons (const GdkPixbuf *src1,
+		 const GdkPixbuf *src2)
+{
+	GdkPixbuf *dest;
+	GdkPixbuf *scaled;
+	gint       w1, w2, h1, h2;
+	gint       dest_x, dest_y;
+	gboolean   do_scale;
+
+	if (! src1) {
+		return NULL;
+	}
+
+	dest = gdk_pixbuf_copy (src1);
+
+	if (! src2) {
+		return dest;
+	}
+
+	w1 = gdk_pixbuf_get_width (src1);
+	h1 = gdk_pixbuf_get_height (src1);
+	w2 = gdk_pixbuf_get_width (src2);
+	h2 = gdk_pixbuf_get_height (src2);
+
+	do_scale = ((float)w1 * 0.8) < w2;
+
+	/* scale the emblem down if it will obscure the entire bottom image */
+	if (do_scale) {
+		scaled = gdk_pixbuf_scale_simple (src2, w1 / 2, h1 / 2, GDK_INTERP_BILINEAR);
+	} else {
+		scaled = (GdkPixbuf *)src2;
+	}
+
+	w2 = gdk_pixbuf_get_width (scaled);
+	h2 = gdk_pixbuf_get_height (scaled);
+
+	dest_x = w1 - w2;
+	dest_y = h1 - h2;
+
+	gdk_pixbuf_composite (scaled, dest,
+			      dest_x, dest_y,
+			      w2, h2,
+			      dest_x, dest_y,
+			      1.0, 1.0,
+			      GDK_INTERP_BILINEAR, 0xFF);
+
+	if (do_scale) {
+		g_object_unref (scaled);
+	}
+
+	return dest;
+}
+
+static void
+create_pixbufs (RBDaapPlugin *plugin)
+{
+	GdkPixbuf    *emblem;
+	GtkIconTheme *theme;
+	gint          size;
+
+	theme = gtk_icon_theme_get_default ();
+
+	gtk_icon_size_lookup (GTK_ICON_SIZE_LARGE_TOOLBAR, &size, NULL);
+	plugin->priv->daap_share_pixbuf =
+		gtk_icon_theme_load_icon (theme, "gnome-fs-network", size, 0, NULL);
+
+	gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &size, NULL);
+	emblem = gtk_icon_theme_load_icon (theme, "stock_lock", size, 0, NULL);
+
+	plugin->priv->daap_share_locked_pixbuf = composite_icons (plugin->priv->daap_share_pixbuf, emblem);
+
+	if (emblem != NULL) {
+		g_object_unref (emblem);
+	}
+}
+
+GdkPixbuf *
+rb_daap_plugin_get_icon (RBDaapPlugin *plugin,
+			 gboolean password_protected,
+			 gboolean connected)
+{
+	GdkPixbuf *icon;
+
+	g_return_val_if_fail (plugin->priv->daap_share_pixbuf != NULL, NULL);
+	g_return_val_if_fail (plugin->priv->daap_share_locked_pixbuf != NULL, NULL);
+
+	if (password_protected == FALSE) {
+		icon = g_object_ref (plugin->priv->daap_share_pixbuf);
+	} else if (connected) {
+		icon = g_object_ref (plugin->priv->daap_share_pixbuf);
+	} else {
+		icon = g_object_ref (plugin->priv->daap_share_locked_pixbuf);
+	}
+
+	return icon;
+}
+
+/* mDNS browsing */
+
+static RBSource *
+find_source_by_service_name (RBDaapPlugin *plugin,
+			     const char *service_name)
+{
+	RBSource *source;
+
+	source = g_hash_table_lookup (plugin->priv->source_lookup, service_name);
+
+	return source;
+}
+
+static void
+mdns_service_added (RBDaapMdnsBrowser *browser,
+		    const char        *service_name,
+		    const char        *name,
+		    const char        *host,
+		    guint              port,
+		    gboolean           password_protected,
+		    RBDaapPlugin      *plugin)
+{
+	RBSource *source;
+
+	rb_debug ("New service: %s name=%s host=%s port=%u password=%d",
+		   service_name, name, host, port, password_protected);
+
+	source = find_source_by_service_name (plugin, service_name);
+
+	if (source == NULL) {
+		source = rb_daap_source_new (plugin->priv->shell, RB_PLUGIN (plugin), service_name, name, host, port, password_protected);
+		g_hash_table_insert (plugin->priv->source_lookup, g_strdup (service_name), source);
+		rb_shell_append_source (plugin->priv->shell, source, NULL);
+	} else {
+		g_object_set (G_OBJECT (source),
+			      "name", name,
+			      "host", host,
+			      "port", port,
+			      "password-protected", password_protected,
+			      NULL);
+	}
+}
+
+static void
+mdns_service_removed (RBDaapMdnsBrowser *browser,
+		      const char        *service_name,
+		      RBDaapPlugin	*plugin)
+{
+	RBSource *source;
+
+	source = find_source_by_service_name (plugin, service_name);
+
+	rb_debug ("DAAP source '%s' went away", service_name);
+	if (source == NULL) {
+		return;
+	}
+
+	g_hash_table_remove (plugin->priv->source_lookup, service_name);
+}
+
+static void
+remove_source (RBSource *source)
+{
+	char *service_name;
+
+	g_object_get (source, "service-name", &service_name, NULL);
+	rb_debug ("Removing DAAP source: %s", service_name);
+
+	rb_daap_source_disconnect (RB_DAAP_SOURCE (source));
+	rb_source_delete_thyself (source);
+
+	g_free (service_name);
+}
+
+static void
+start_browsing (RBDaapPlugin *plugin)
+{
+	GError *error;
+
+	if (plugin->priv->mdns_browser != NULL) {
+		return;
+	}
+
+	plugin->priv->mdns_browser = rb_daap_mdns_browser_new ();
+	if (plugin->priv->mdns_browser == NULL) {
+		g_warning ("Unable to start mDNS browsing");
+		return;
+	}
+
+	g_signal_connect_object (plugin->priv->mdns_browser,
+				 "service-added",
+				 G_CALLBACK (mdns_service_added),
+				 plugin,
+				 0);
+	g_signal_connect_object (plugin->priv->mdns_browser,
+				 "service-removed",
+				 G_CALLBACK (mdns_service_removed),
+				 plugin,
+				 0);
+
+	error = NULL;
+	rb_daap_mdns_browser_start (plugin->priv->mdns_browser, &error);
+	if (error != NULL) {
+		g_warning ("Unable to start mDNS browsing: %s", error->message);
+		g_error_free (error);
+	}
+
+	plugin->priv->source_lookup = g_hash_table_new_full ((GHashFunc)g_str_hash,
+							     (GEqualFunc)g_str_equal,
+							     (GDestroyNotify)g_free,
+							     (GDestroyNotify)remove_source);
+}
+
+static void
+stop_browsing (RBDaapPlugin *plugin)
+{
+	GError *error;
+
+	if (plugin->priv->mdns_browser == NULL) {
+		return;
+	}
+
+	rb_debug ("Destroying DAAP source lookup");
+
+	g_hash_table_destroy (plugin->priv->source_lookup);
+	plugin->priv->source_lookup = NULL;
+
+	g_signal_handlers_disconnect_by_func (plugin->priv->mdns_browser, mdns_service_added, plugin);
+	g_signal_handlers_disconnect_by_func (plugin->priv->mdns_browser, mdns_service_removed, plugin);
+
+	error = NULL;
+	rb_daap_mdns_browser_stop (plugin->priv->mdns_browser, &error);
+	if (error != NULL) {
+		g_warning ("Unable to stop mDNS browsing: %s", error->message);
+		g_error_free (error);
+	}
+
+	g_object_unref (plugin->priv->mdns_browser);
+	plugin->priv->mdns_browser = NULL;
+}
+
+static void
+enable_browsing_changed_cb (GConfClient *client,
+			    guint cnxn_id,
+			    GConfEntry *entry,
+			    RBDaapPlugin *plugin)
+{
+	gboolean enabled = eel_gconf_get_boolean (CONF_ENABLE_BROWSING);
+
+	if (enabled) {
+		start_browsing (plugin);
+	} else {
+		stop_browsing (plugin);
+	}
+}
+
+/* daap:// URI -> RBDAAPSource mapping */
+
+static gboolean
+source_host_find (const char *key,
+		  RBDAAPSource *source,
+		  const char *host)
+{
+	char *source_host;
+	gboolean result;
+
+	if (source == NULL || host == NULL) {
+		return FALSE;
+	}
+
+	g_object_get (source, "host", &source_host, NULL);
+
+	result = (strcmp (host, source_host) == 0);
+	g_free (source_host);
+
+	return result;
+}
+
+RBDAAPSource *
+rb_daap_plugin_find_source_for_uri (RBDaapPlugin *plugin, const char *uri)
+{
+	char *ip;
+	char *s;
+	RBDAAPSource *source = NULL;
+
+	if (uri == NULL) {
+		return NULL;
+	}
+
+	ip = strdup (uri + 7); /* daap:// */
+	s = strchr (ip, ':');
+	*s = '\0';
+
+	source = (RBDAAPSource *)g_hash_table_find (plugin->priv->source_lookup, (GHRFunc)source_host_find, ip);
+
+	g_free (ip);
+
+	return source;
+}
+
+/* preferences dialog */
+
+static void
+preferences_response_cb (GtkWidget *dialog, gint response, RBPlugin *plugin)
+{
+	gtk_widget_hide (dialog);
+}
+
+static void
+share_check_button_toggled_cb (GtkToggleButton *button,
+			       GtkWidget *widget)
+{
+	gboolean b;
+
+	b = gtk_toggle_button_get_active (button);
+
+	eel_gconf_set_boolean (CONF_DAAP_ENABLE_SHARING, b);
+
+	gtk_widget_set_sensitive (widget, b);
+}
+
+static void
+password_check_button_toggled_cb (GtkToggleButton *button,
+				  GtkWidget *widget)
+{
+	gboolean b;
+
+	b = gtk_toggle_button_get_active (button);
+
+	eel_gconf_set_boolean (CONF_DAAP_REQUIRE_PASSWORD, b);
+
+	gtk_widget_set_sensitive (widget, b);
+}
+
+static gboolean
+share_name_entry_focus_out_event_cb (GtkEntry *entry,
+				     GdkEventFocus *event,
+				     gpointer data)
+{
+	gboolean    changed;
+	const char *name;
+	char       *old_name;
+
+	name = gtk_entry_get_text (entry);
+	old_name = eel_gconf_get_string (CONF_DAAP_SHARE_NAME);
+
+	if (name == NULL && old_name == NULL) {
+		changed = FALSE;
+	} else if (name == NULL || old_name == NULL) {
+		changed = TRUE;
+	} else if (strcmp (name, old_name) != 0) {
+		changed = TRUE;
+	} else {
+		changed = FALSE;
+	}
+
+	if (changed)
+		eel_gconf_set_string (CONF_DAAP_SHARE_NAME, name);
+
+	g_free (old_name);
+
+	return FALSE;
+}
+
+static gboolean
+share_password_entry_focus_out_event_cb (GtkEntry *entry,
+					 GdkEventFocus *event,
+					 gpointer data)
+{
+	gboolean    changed;
+	const char *pw;
+	char       *old_pw;
+
+	pw = gtk_entry_get_text (entry);
+	old_pw = eel_gconf_get_string (CONF_DAAP_SHARE_PASSWORD);
+
+	if (pw == NULL && old_pw == NULL) {
+		changed = FALSE;
+	} else if (pw == NULL || old_pw == NULL) {
+		changed = TRUE;
+	} else if (strcmp (pw, old_pw) != 0) {
+		changed = TRUE;
+	} else {
+		changed = FALSE;
+	}
+
+	if (changed)
+		eel_gconf_set_string (CONF_DAAP_SHARE_PASSWORD, pw);
+
+	g_free (old_pw);
+
+	return FALSE;
+}
+
+static GtkWidget *
+make_config_widget (RBPlugin *plugin)
+{
+	GladeXML *xml;
+	GtkWidget *check;
+	GtkWidget *name_entry;
+	GtkWidget *password_entry;
+	GtkWidget *password_check;
+	GtkWidget *box;
+	gboolean sharing_enabled;
+	gboolean require_password;
+
+	char *name;
+	char *password;
+	char *gladefile;
+
+	gladefile = rb_plugin_find_file (plugin, "daap-prefs.glade");
+	if (gladefile == NULL) {
+		gladefile = g_strdup (rb_file ("daap-prefs.glade"));
+		if (gladefile == NULL) {
+			return NULL;
+		}
+	}
+
+	xml = glade_xml_new (gladefile, "daap_vbox", NULL);
+	g_free (gladefile);
+
+	check = glade_xml_get_widget (xml, "daap_enable_check");
+	password_check = glade_xml_get_widget (xml, "daap_password_check");
+	name_entry = glade_xml_get_widget (xml, "daap_name_entry");
+	password_entry = glade_xml_get_widget (xml, "daap_password_entry");
+	box = glade_xml_get_widget (xml, "daap_box");
+
+	sharing_enabled = eel_gconf_get_boolean (CONF_DAAP_ENABLE_SHARING);
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), sharing_enabled);
+	g_signal_connect (check, "toggled", G_CALLBACK (share_check_button_toggled_cb), box);
+
+	require_password = eel_gconf_get_boolean (CONF_DAAP_REQUIRE_PASSWORD);
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (password_check), require_password);
+	g_signal_connect (password_check, "toggled", G_CALLBACK (password_check_button_toggled_cb), password_entry);
+
+	name = eel_gconf_get_string (CONF_DAAP_SHARE_NAME);
+	if (name != NULL)
+		gtk_entry_set_text (GTK_ENTRY (name_entry), name);
+	g_free (name);
+	g_signal_connect (name_entry, "focus-out-event",
+			  G_CALLBACK (share_name_entry_focus_out_event_cb), NULL);
+
+	password = eel_gconf_get_string (CONF_DAAP_SHARE_PASSWORD);
+	if (password != NULL)
+		gtk_entry_set_text (GTK_ENTRY (password_entry), password);
+	g_free (password);
+	g_signal_connect (password_entry, "focus-out-event",
+			  G_CALLBACK (share_password_entry_focus_out_event_cb), NULL);
+
+	gtk_widget_set_sensitive (box, sharing_enabled);
+	gtk_widget_set_sensitive (password_entry, require_password);
+
+	return glade_xml_get_widget (xml, "daap_vbox");
+}
+
+static GtkWidget*
+impl_create_configure_dialog (RBPlugin *bplugin)
+{
+	RBDaapPlugin *plugin = RB_DAAP_PLUGIN (bplugin);
+
+	if (plugin->priv->preferences == NULL) {
+		GtkWidget *widget;
+
+		widget =  make_config_widget (bplugin);
+
+		plugin->priv->preferences = gtk_dialog_new_with_buttons (_("DAAP Music Sharing Preferences"),
+								   NULL,
+								   GTK_DIALOG_DESTROY_WITH_PARENT,
+								   GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
+								   NULL);
+		g_signal_connect (G_OBJECT (plugin->priv->preferences),
+				  "response",
+				  G_CALLBACK (preferences_response_cb),
+				  plugin);
+		gtk_widget_hide_on_delete (plugin->priv->preferences);
+
+		gtk_container_add (GTK_CONTAINER (GTK_DIALOG (plugin->priv->preferences)->vbox), widget);
+	}
+
+	gtk_widget_show_all (plugin->priv->preferences);
+	return plugin->priv->preferences;
+}
+
diff -rN -u -p old-daap/plugins/Makefile.am new-daap/plugins/Makefile.am
--- old-daap/plugins/Makefile.am	2006-11-04 20:39:02.000000000 +1000
+++ new-daap/plugins/Makefile.am	2006-11-04 20:39:03.000000000 +1000
@@ -38,6 +38,10 @@ if WITH_DBUS
 SUBDIRS += power-manager
 endif
 
+if USE_DAAP
+SUBDIRS += daap
+endif
+
 noinst_LTLIBRARIES = librbplugins.la
 
 librbplugins_la_SOURCES =				\
diff -rN -u -p old-daap/shell/Makefile.am new-daap/shell/Makefile.am
--- old-daap/shell/Makefile.am	2006-11-04 20:39:02.000000000 +1000
+++ new-daap/shell/Makefile.am	2006-11-04 20:39:03.000000000 +1000
@@ -104,16 +104,6 @@ rhythmbox_LDADD =					\
 	$(top_builddir)/plugins/librbplugins.la		\
 	$(top_builddir)/lib/librb.la
 
-if USE_DAAP
-INCLUDES += -I$(top_srcdir)/daapsharing
-
-rhythmbox_LDADD += $(MDNS_LIBS) \
-		   $(top_builddir)/daapsharing/libdaapsharing.la
-if USE_GNOME_KEYRING
-rhythmbox_LDADD += $(GNOME_KEYRING_LIBS)
-endif
-endif
-
 if USE_LIBSOUP
 rhythmbox_LDADD += $(SOUP_LIBS)
 INCLUDES += $(SOUP_CFLAGS)
diff -rN -u -p old-daap/shell/rb-shell.c new-daap/shell/rb-shell.c
--- old-daap/shell/rb-shell.c	2006-11-04 20:39:02.000000000 +1000
+++ new-daap/shell/rb-shell.c	2006-11-04 20:39:03.000000000 +1000
@@ -72,10 +72,6 @@
 #include "rb-library-source.h"
 #include "rb-podcast-source.h"
 #include "totem-pl-parser.h"
-#ifdef WITH_DAAP_SUPPORT
-#include "rb-daap-source.h"
-#include "rb-daap-sharing.h"
-#endif /* WITH_DAAP_SUPPORT */
 #include "rb-shell-preferences.h"
 #include "rb-playlist-source.h"
 #include "rb-static-playlist-source.h"
@@ -1188,12 +1184,6 @@ construct_sources (RBShell *shell)
 	g_signal_connect_object (G_OBJECT (shell->priv->playlist_manager), "playlist_created",
 				 G_CALLBACK (rb_shell_playlist_created_cb), shell, 0);
 
-#ifdef WITH_DAAP_SUPPORT
-	rb_daap_sources_init (shell);
-	if (!shell->priv->no_registration)
-		rb_daap_sharing_init (shell);
-#endif
-
 	/* Initialize removable media manager */
 	rb_debug ("shell: creating removable media manager");
 	shell->priv->removable_media_manager = rb_removable_media_manager_new (shell,
@@ -2398,11 +2388,6 @@ rb_shell_quit (RBShell *shell,
 
 	rb_podcast_source_shutdown (shell->priv->podcast_source);
 
-#ifdef WITH_DAAP_SUPPORT
-	rb_daap_sources_shutdown (shell);
-	if (!shell->priv->no_registration)
-		rb_daap_sharing_shutdown (shell);
-#endif /* WITH_DAAP_SUPPORT */
 	rb_shell_shutdown (shell);
 	rb_shell_sync_state (shell);
 	g_object_unref (G_OBJECT (shell));
diff -rN -u -p old-daap/shell/rb-shell-preferences.c new-daap/shell/rb-shell-preferences.c
--- old-daap/shell/rb-shell-preferences.c	2006-11-04 20:39:02.000000000 +1000
+++ new-daap/shell/rb-shell-preferences.c	2006-11-04 20:39:03.000000000 +1000
@@ -269,158 +269,6 @@ rb_shell_preferences_append_view_page (R
 	rb_shell_preferences_append_page (prefs, name, widget);
 }
 
-#ifdef WITH_DAAP_SUPPORT
-
-static void
-share_check_button_toggled_cb (GtkToggleButton *button,
-			       GtkWidget *widget)
-{
-	gboolean b;
-
-	b = gtk_toggle_button_get_active (button);
-
-	eel_gconf_set_boolean (CONF_DAAP_ENABLE_SHARING, b);
-
-	gtk_widget_set_sensitive (widget, b);
-
-	return;
-}
-
-static void
-password_check_button_toggled_cb (GtkToggleButton *button,
-				  GtkWidget *widget)
-{
-	gboolean b;
-
-	b = gtk_toggle_button_get_active (button);
-
-	eel_gconf_set_boolean (CONF_DAAP_REQUIRE_PASSWORD, b);
-
-	gtk_widget_set_sensitive (widget, b);
-
-	return;
-}
-
-static gboolean
-share_name_entry_focus_out_event_cb (GtkEntry *entry,
-				     GdkEventFocus *event,
-				     gpointer data)
-{
-	gboolean    changed;
-	const char *name;
-	char       *old_name;
-
-	name = gtk_entry_get_text (entry);
-	old_name = eel_gconf_get_string (CONF_DAAP_SHARE_NAME);
-
-	if (name == NULL && old_name == NULL) {
-		changed = FALSE;
-	} else if (name == NULL || old_name == NULL) {
-		changed = TRUE;
-	} else if (strcmp (name, old_name) != 0) {
-		changed = TRUE;
-	} else {
-		changed = FALSE;
-	}
-
-	if (changed) {
-		eel_gconf_set_string (CONF_DAAP_SHARE_NAME, name);
-	}
-
-	g_free (old_name);
-
-	return FALSE;
-}
-
-static gboolean
-share_password_entry_focus_out_event_cb (GtkEntry *entry,
-					 GdkEventFocus *event,
-					 gpointer data)
-{
-	gboolean    changed;
-	const char *pw;
-	char       *old_pw;
-
-	pw = gtk_entry_get_text (entry);
-	old_pw = eel_gconf_get_string (CONF_DAAP_SHARE_PASSWORD);
-
-	if (pw == NULL && old_pw == NULL) {
-		changed = FALSE;
-	} else if (pw == NULL || old_pw == NULL) {
-		changed = TRUE;
-	} else if (strcmp (pw, old_pw) != 0) {
-		changed = TRUE;
-	} else {
-		changed = FALSE;
-	}
-
-	if (changed) {
-		eel_gconf_set_string (CONF_DAAP_SHARE_PASSWORD, pw);
-	}
-
-	g_free (old_pw);
-
-	return FALSE;
-}
-
-static void
-add_daap_preferences (RBShellPreferences *shell_preferences)
-{
-	GladeXML *xml;
-	GtkWidget *check;
-	GtkWidget *name_entry;
-	GtkWidget *password_entry;
-	GtkWidget *password_check;
-	GtkWidget *box;
-	gboolean sharing_enabled;
-	gboolean require_password;
-
-	char *name;
-	char *password;
-
-	xml = rb_glade_xml_new ("daap-prefs.glade",
-				"daap_vbox",
-				shell_preferences);
-
-	check = glade_xml_get_widget (xml, "daap_enable_check");
-	password_check = glade_xml_get_widget (xml, "daap_password_check");
-	name_entry = glade_xml_get_widget (xml, "daap_name_entry");
-	password_entry = glade_xml_get_widget (xml, "daap_password_entry");
-	box = glade_xml_get_widget (xml, "daap_box");
-
-	sharing_enabled = eel_gconf_get_boolean (CONF_DAAP_ENABLE_SHARING);
-	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), sharing_enabled);
-	g_signal_connect (check, "toggled", G_CALLBACK (share_check_button_toggled_cb), box);
-
-	require_password = eel_gconf_get_boolean (CONF_DAAP_REQUIRE_PASSWORD);
-	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (password_check), require_password);
-	g_signal_connect (password_check, "toggled", G_CALLBACK (password_check_button_toggled_cb), password_entry);
-
-	name = eel_gconf_get_string (CONF_DAAP_SHARE_NAME);
-	if (name != NULL) {
-		gtk_entry_set_text (GTK_ENTRY (name_entry), name);
-	}
-	g_free (name);
-	g_signal_connect (name_entry, "focus-out-event",
-			  G_CALLBACK (share_name_entry_focus_out_event_cb), NULL);
-
-	password = eel_gconf_get_string (CONF_DAAP_SHARE_PASSWORD);
-	if (password != NULL) {
-		gtk_entry_set_text (GTK_ENTRY (password_entry), password);
-	}
-	g_free (password);
-	g_signal_connect (password_entry, "focus-out-event",
-			  G_CALLBACK (share_password_entry_focus_out_event_cb), NULL);
-
-	gtk_widget_set_sensitive (box, sharing_enabled);
-	gtk_widget_set_sensitive (password_entry, require_password);
-
-	gtk_notebook_append_page (GTK_NOTEBOOK (shell_preferences->priv->notebook),
-				  glade_xml_get_widget (xml, "daap_vbox"),
-				  gtk_label_new (_("Sharing")));
-}
-#endif /* WITH_DAAP_SUPPORT */
-
 GtkWidget *
 rb_shell_preferences_new (GList *views)
 {
@@ -442,10 +290,6 @@ rb_shell_preferences_new (GList *views)
 		g_free (name);
 	}
 
-#ifdef WITH_DAAP_SUPPORT
-	add_daap_preferences (shell_preferences);
-#endif /* WITH_DAAP_SUPPORT */
-
 	return GTK_WIDGET (shell_preferences);
 }
 
diff -rN -u -p old-daap/sources/Makefile.am new-daap/sources/Makefile.am
--- old-daap/sources/Makefile.am	2006-11-04 20:39:02.000000000 +1000
+++ new-daap/sources/Makefile.am	2006-11-04 20:39:03.000000000 +1000
@@ -48,7 +48,6 @@ INCLUDES =						\
 	-I$(top_srcdir)/iradio				\
 	-I$(top_srcdir)/podcast				\
 	-I$(top_srcdir)/shell				\
-	-I$(top_srcdir)/daapsharing			\
 	-I$(top_srcdir)/backends			\
 	-I$(top_srcdir)/plugins				\
 	-DPIXMAP_DIR=\""$(datadir)/pixmaps"\"		\
@@ -62,17 +61,6 @@ INCLUDES =						\
 libsources_la_LDFLAGS = -export-dynamic
 libsourcesimpl_la_LDFLAGS = -export-dynamic
 
-daap_files =				\
-	rb-daap-source.c		\
-	rb-daap-source.h
-if USE_DAAP
-libsourcesimpl_la_SOURCES += $(daap_files)
-if USE_GNOME_KEYRING
-INCLUDES +=						\
-	$(GNOME_KEYRING_CFLAGS)
-endif
-endif
-
 if USE_LIBSOUP
 INCLUDES += $(SOUP_CFLAGS)
 endif
@@ -81,4 +69,3 @@ if ENABLE_TRACK_TRANSFER
 INCLUDES +=$(GNOME_MEDIA_PROFILES_CFLAGS)
 endif
 
-EXTRA_DIST = $(daap_files)
diff -rN -u -p old-daap/sources/rb-daap-source.c new-daap/sources/rb-daap-source.c
--- old-daap/sources/rb-daap-source.c	2006-11-04 20:39:02.000000000 +1000
+++ new-daap/sources/rb-daap-source.c	2006-11-04 20:39:03.000000000 +1000
@@ -49,6 +49,7 @@
 #include "rb-daap-connection.h"
 #include "rb-daap-mdns-browser.h"
 #include "rb-daap-dialog.h"
+#include "rb-daap-plugin.h"
 
 #include "rb-static-playlist-source.h"
 
@@ -67,24 +68,11 @@ static gboolean rb_daap_source_show_popu
 static char * rb_daap_source_get_browser_key (RBSource *source);
 static const char * rb_daap_source_get_paned_key (RBBrowserSource *source);
 static void rb_daap_source_get_status (RBSource *source, char **text, char **progress_text, float *progress);
-static void rb_daap_source_cmd_disconnect (GtkAction *action, RBShell *shell);
-static void rb_daap_source_disconnect (RBDAAPSource *daap_source);
 
-#define CONF_ENABLE_BROWSING CONF_PREFIX "/sharing/enable_browsing"
 #define CONF_STATE_SORTING CONF_PREFIX "/state/daap/sorting"
 #define CONF_STATE_PANED_POSITION CONF_PREFIX "/state/daap/paned_position"
 #define CONF_STATE_SHOW_BROWSER CONF_PREFIX "/state/daap/show_browser"
 
-static RBDaapMdnsBrowser *mdns_browser = NULL;
-
-static GHashTable *source_lookup = NULL;
-
-static guint enable_browsing_notify_id = EEL_GCONF_UNDEFINED_CONNECTION;
-
-static GdkPixbuf *daap_share_pixbuf        = NULL;
-static GdkPixbuf *daap_share_locked_pixbuf = NULL;
-static gboolean daap_was_shutdown = FALSE;
-
 struct RBDAAPSourcePrivate
 {
 	GtkActionGroup *action_group;
@@ -115,15 +103,6 @@ enum {
 
 G_DEFINE_TYPE (RBDAAPSource, rb_daap_source, RB_TYPE_BROWSER_SOURCE)
 
-static GtkActionEntry rb_daap_source_actions [] =
-{
-	{ "DaapSourceDisconnect", GTK_STOCK_DISCONNECT, N_("_Disconnect"), NULL,
-	  N_("Disconnect from DAAP share"),
-	  G_CALLBACK (rb_daap_source_cmd_disconnect) },
-};
-GtkActionGroup *daap_action_group;
-guint daap_ui_merge_id;
-
 static void
 rb_daap_source_dispose (GObject *object)
 {
@@ -208,11 +187,6 @@ rb_daap_source_class_init (RBDAAPSourceC
 							       G_PARAM_READWRITE));
 
 	g_type_class_add_private (klass, sizeof (RBDAAPSourcePrivate));
-
-#ifdef HAVE_GSTREAMER
-	/* small hack to ensure the linker doesn't drop the daap src code */
-	rb_daap_src_get_type ();
-#endif
 }
 
 static void
@@ -282,28 +256,10 @@ rb_daap_source_get_property (GObject *ob
 	}
 }
 
-static GdkPixbuf *
-rb_daap_get_icon (gboolean password_protected,
-		  gboolean connected)
-{
-	GdkPixbuf *icon;
 
-	g_return_val_if_fail (daap_share_pixbuf != NULL, NULL);
-	g_return_val_if_fail (daap_share_locked_pixbuf != NULL, NULL);
-
-	if (! password_protected) {
-		icon = g_object_ref (daap_share_pixbuf);
-	} else if (connected) {
-		icon = g_object_ref (daap_share_pixbuf);
-	} else {
-		icon = g_object_ref (daap_share_locked_pixbuf);
-	}
-
-	return icon;
-}
-
-static RBSource *
+RBSource *
 rb_daap_source_new (RBShell *shell,
+		    RBPlugin *plugin,
 		    const char *service_name,
 		    const char *name,
 		    const char *host,
@@ -321,7 +277,7 @@ rb_daap_source_new (RBShell *shell,
 	type->category = RHYTHMDB_ENTRY_NORMAL;
 	g_object_unref (db);
 
-	icon = rb_daap_get_icon (password_protected, FALSE);
+	icon = rb_daap_plugin_get_icon (RB_DAAP_PLUGIN (plugin), password_protected, FALSE);
 	source = RB_SOURCE (g_object_new (RB_TYPE_DAAP_SOURCE,
 					  "service-name", service_name,
 					  "name", name,
@@ -334,6 +290,7 @@ rb_daap_source_new (RBShell *shell,
 					  "sorting-key", CONF_STATE_SORTING,
 					  "password-protected", password_protected,
 					  "sourcelist-group", RB_SOURCELIST_GROUP_TRANSIENT,
+					  "plugin", RB_PLUGIN (plugin),
 					  NULL));
 
 	if (icon != NULL) {
@@ -346,327 +303,6 @@ rb_daap_source_new (RBShell *shell,
 	return source;
 }
 
-static RBSource *
-find_source_by_service_name (const char *service_name)
-{
-	RBSource *source;
-
-	source = g_hash_table_lookup (source_lookup, service_name);
-
-	return source;
-}
-
-static void
-mdns_service_added (RBDaapMdnsBrowser *browser,
-		    const char        *service_name,
-		    const char        *name,
-		    const char        *host,
-		    guint              port,
-		    gboolean           password_protected,
-		    RBShell           *shell)
-{
-	RBSource *source;
-
-#if 0
-	g_message ("New service: %s name=%s host=%s port=%u password=%d",
-		   service_name, name, host, port, password_protected);
-#endif
-
-	source = find_source_by_service_name (service_name);
-
-	if (source == NULL) {
-		source = rb_daap_source_new (shell, service_name, name, host, port, password_protected);
-		g_hash_table_insert (source_lookup, g_strdup (service_name), source);
-		rb_shell_append_source (shell, source, NULL);
-	} else {
-		g_object_set (G_OBJECT (source),
-			      "name", name,
-			      "host", host,
-			      "port", port,
-			      "password-protected", password_protected,
-			      NULL);
-	}
-}
-
-static void
-mdns_service_removed (RBDaapMdnsBrowser *browser,
-		      const char        *service_name,
-		      RBShell           *shell)
-{
-	RBSource *source;
-
-	source = find_source_by_service_name (service_name);
-
-	rb_debug ("DAAP source '%s' went away", service_name);
-	if (source == NULL) {
-		return;
-	}
-
-	g_hash_table_remove (source_lookup, service_name);
-}
-
-static void
-remove_source (RBSource *source)
-{
-	rb_debug ("Removing DAAP source: %s", RB_DAAP_SOURCE (source)->priv->service_name);
-	rb_daap_source_disconnect (RB_DAAP_SOURCE (source));
-	rb_source_delete_thyself (source);
-}
-
-static void
-start_browsing (RBShell *shell)
-{
-	GError *error;
-
-	if (mdns_browser != NULL) {
-		return;
-	}
-
-	mdns_browser = rb_daap_mdns_browser_new ();
-	if (mdns_browser == NULL) {
-		g_warning ("Unable to start mDNS browsing");
-		return;
-	}
-
-	g_signal_connect_object (mdns_browser,
-				 "service-added",
-				 G_CALLBACK (mdns_service_added),
-				 shell,
-				 0);
-	g_signal_connect_object (mdns_browser,
-				 "service-removed",
-				 G_CALLBACK (mdns_service_removed),
-				 shell,
-				 0);
-
-	error = NULL;
-	rb_daap_mdns_browser_start (mdns_browser, &error);
-	if (error != NULL) {
-		g_warning ("Unable to start mDNS browsing: %s", error->message);
-		g_error_free (error);
-	}
-
-	source_lookup = g_hash_table_new_full ((GHashFunc)g_str_hash,
-					       (GEqualFunc)g_str_equal,
-					       (GDestroyNotify)g_free,
-					       (GDestroyNotify)remove_source);
-
-}
-
-static void
-stop_browsing (RBShell *shell)
-{
-	GError *error;
-
-	if (mdns_browser == NULL) {
-		return;
-	}
-
-	rb_debug ("Destroying DAAP source lookup");
-
-	g_hash_table_destroy (source_lookup);
-	source_lookup = NULL;
-
-	g_signal_handlers_disconnect_by_func (mdns_browser, mdns_service_added, shell);
-	g_signal_handlers_disconnect_by_func (mdns_browser, mdns_service_removed, shell);
-
-	error = NULL;
-	rb_daap_mdns_browser_stop (mdns_browser, &error);
-	if (error != NULL) {
-		g_warning ("Unable to stop mDNS browsing: %s", error->message);
-		g_error_free (error);
-	}
-
-	g_object_unref (mdns_browser);
-	mdns_browser = NULL;
-}
-
-static void
-enable_browsing_changed_cb (GConfClient *client,
-			    guint cnxn_id,
-			    GConfEntry *entry,
-			    RBShell *shell)
-{
-	gboolean enabled = eel_gconf_get_boolean (CONF_ENABLE_BROWSING);
-
-	if (enabled) {
-		start_browsing (shell);
-	} else {
-		stop_browsing (shell);
-	}
-}
-
-static GdkPixbuf *
-composite_icons (const GdkPixbuf *src1,
-		 const GdkPixbuf *src2)
-{
-	GdkPixbuf *dest;
-	GdkPixbuf *scaled;
-	gint       w1, w2, h1, h2;
-	gint       dest_x, dest_y;
-	gboolean   do_scale;
-
-	if (! src1) {
-		return NULL;
-	}
-
-	dest = gdk_pixbuf_copy (src1);
-
-	if (! src2) {
-		return dest;
-	}
-
-	w1 = gdk_pixbuf_get_width (src1);
-	h1 = gdk_pixbuf_get_height (src1);
-	w2 = gdk_pixbuf_get_width (src2);
-	h2 = gdk_pixbuf_get_height (src2);
-
-	do_scale = ((float)w1 * 0.8) < w2;
-
-	/* scale the emblem down if it will obscure the entire bottom image */
-	if (do_scale) {
-		scaled = gdk_pixbuf_scale_simple (src2, w1 / 2, h1 / 2, GDK_INTERP_BILINEAR);
-	} else {
-		scaled = (GdkPixbuf *)src2;
-	}
-
-	w2 = gdk_pixbuf_get_width (scaled);
-	h2 = gdk_pixbuf_get_height (scaled);
-
-	dest_x = w1 - w2;
-	dest_y = h1 - h2;
-
-	gdk_pixbuf_composite (scaled, dest,
-			      dest_x, dest_y,
-			      w2, h2,
-			      dest_x, dest_y,
-			      1.0, 1.0,
-			      GDK_INTERP_BILINEAR, 0xFF);
-
-	if (do_scale) {
-		g_object_unref (scaled);
-	}
-
-	return dest;
-}
-
-static void
-create_pixbufs (void)
-{
-	GdkPixbuf    *emblem;
-	GtkIconTheme *theme;
-	gint          size;
-
-	theme = gtk_icon_theme_get_default ();
-
-	gtk_icon_size_lookup (GTK_ICON_SIZE_LARGE_TOOLBAR, &size, NULL);
-	daap_share_pixbuf = gtk_icon_theme_load_icon (theme, "gnome-fs-network", size, 0, NULL);
-
-	gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &size, NULL);
-	emblem = gtk_icon_theme_load_icon (theme, "stock_lock", size, 0, NULL);
-
-	daap_share_locked_pixbuf = composite_icons (daap_share_pixbuf, emblem);
-
-	if (emblem != NULL) {
-		g_object_unref (emblem);
-	}
-}
-
-static void
-destroy_pixbufs (void)
-{
-	if (daap_share_pixbuf != NULL) {
-		g_object_unref (daap_share_pixbuf);
-	}
-
-	daap_share_pixbuf = NULL;
-
-	if (daap_share_locked_pixbuf != NULL) {
-		g_object_unref (daap_share_locked_pixbuf);
-	}
-	daap_share_locked_pixbuf = NULL;
-}
-
-RBSource *
-rb_daap_sources_init (RBShell *shell)
-{
-	gboolean enabled = TRUE;
-	GConfValue *value;
-	GConfClient *client = eel_gconf_client_get_global ();
-	GtkUIManager *uimanager = NULL;
-
-	value = gconf_client_get_without_default (client,
-						  CONF_ENABLE_BROWSING, NULL);
-	if (value != NULL) {
-		enabled = gconf_value_get_bool (value);
-		gconf_value_free (value);
-	}
-
-	g_object_ref (shell);
-
-	if (enabled) {
-		start_browsing (shell);
-	}
-
-	enable_browsing_notify_id =
-		eel_gconf_notification_add (CONF_ENABLE_BROWSING,
-					    (GConfClientNotifyFunc) enable_browsing_changed_cb,
-					    shell);
-
-	create_pixbufs ();
-
-	/* add UI */
-	g_object_get (shell,
-		      "ui-manager", &uimanager,
-		      NULL);
-	daap_action_group = gtk_action_group_new ("DaapActions");
-	gtk_action_group_set_translation_domain (daap_action_group,
-						 GETTEXT_PACKAGE);
-	gtk_action_group_add_actions (daap_action_group,
-				      rb_daap_source_actions, G_N_ELEMENTS (rb_daap_source_actions),
-				      shell);
-	gtk_ui_manager_insert_action_group (uimanager, daap_action_group, 0);
-	daap_ui_merge_id = gtk_ui_manager_add_ui_from_file (uimanager,
-							    rb_file ("daap-ui.xml"),
-							    NULL);
-	g_object_unref (uimanager);
-
-	return NULL;
-}
-
-void
-rb_daap_sources_shutdown (RBShell *shell)
-{
-	GtkUIManager *uimanager = NULL;
-
-	if (daap_was_shutdown)
-		return;
-
-	rb_debug ("Shutting down DAAP sources");
-	daap_was_shutdown = TRUE;
-
-	g_object_get (shell,
-		      "ui-manager", &uimanager,
-		      NULL);
-
-	if (mdns_browser) {
-		stop_browsing (shell);
-	}
-
-	if (enable_browsing_notify_id != EEL_GCONF_UNDEFINED_CONNECTION) {
-		eel_gconf_notification_remove (enable_browsing_notify_id);
-		enable_browsing_notify_id = EEL_GCONF_UNDEFINED_CONNECTION;
-	}
-
-	gtk_ui_manager_remove_ui (uimanager, daap_ui_merge_id);
-	gtk_ui_manager_remove_action_group (uimanager, daap_action_group);
-
-	g_object_unref (uimanager);
-	g_object_unref (shell);
-
-	destroy_pixbufs ();
-}
-
 static char *
 connection_auth_cb (RBDAAPConnection *connection,
 		    const char       *name,
@@ -683,7 +319,7 @@ connection_auth_cb (RBDAAPConnection *co
 		keyringret = gnome_keyring_find_network_password_sync (
 				NULL,
 				"DAAP", name,
-				NULL, "daap", 
+				NULL, "daap",
 				NULL, 0, &list);
 	} else {
 		keyringret = GNOME_KEYRING_RESULT_CANCELLED;
@@ -733,9 +369,9 @@ connection_auth_cb (RBDAAPConnection *co
 				gnome_keyring_set_network_password_sync (keyring,
 					NULL,
 					"DAAP", name,
-					NULL, "daap", 
-					NULL, 0, 
-					password, 
+					NULL, "daap",
+					NULL, 0,
+					password,
 					&item_id);
 				break;
 			}
@@ -769,6 +405,7 @@ connection_connecting_cb (RBDAAPConnecti
 {
 	GdkPixbuf *icon;
 	gboolean   is_connected;
+	RBPlugin  *plugin;
 
 	rb_debug ("DAAP connection status: %d/%f", state, progress);
 
@@ -796,11 +433,19 @@ connection_connecting_cb (RBDAAPConnecti
 	rb_source_notify_status_changed (RB_SOURCE (source));
 
 	is_connected = rb_daap_connection_is_connected (connection);
-	icon = rb_daap_get_icon (source->priv->password_protected, is_connected);
+
+	g_object_get (source, "plugin", &plugin, NULL);
+	g_assert (plugin != NULL);
+
+	icon = rb_daap_plugin_get_icon (RB_DAAP_PLUGIN (plugin),
+					source->priv->password_protected,
+					is_connected);
 	g_object_set (source, "icon", icon, NULL);
 	if (icon != NULL) {
 		g_object_unref (icon);
 	}
+
+	g_object_unref (plugin);
 }
 
 static void
@@ -808,18 +453,27 @@ connection_disconnected_cb (RBDAAPConnec
 			    RBDAAPSource     *source)
 {
 	GdkPixbuf *icon;
+	RBPlugin  *plugin;
+	gboolean   daap_shutdown;
 
 	rb_debug ("DAAP connection disconnected");
 
-	if (daap_was_shutdown) {
-		return;
-	}
+	g_object_get (source, "plugin", &plugin, NULL);
+	g_assert (plugin != NULL);
 
-	icon = rb_daap_get_icon (source->priv->password_protected, FALSE);
-	g_object_set (source, "icon", icon, NULL);
-	if (icon != NULL) {
-		g_object_unref (icon);
+	g_object_get (plugin, "shutdown", &daap_shutdown, NULL);
+	if (daap_shutdown == FALSE) {
+
+		icon = rb_daap_plugin_get_icon (RB_DAAP_PLUGIN (plugin),
+						source->priv->password_protected,
+						FALSE);
+		g_object_set (source, "icon", icon, NULL);
+		if (icon != NULL) {
+			g_object_unref (icon);
+		}
 	}
+
+	g_object_unref (plugin);
 }
 
 static void
@@ -827,9 +481,7 @@ release_connection (RBDAAPSource *daap_s
 {
 	rb_debug ("Releasing connection");
 
-	g_object_unref (G_OBJECT (daap_source->priv->connection));
-	/* Weak pointer will set to NULL for us */
-	/*daap_source->priv->connection = NULL;*/
+	g_object_unref (daap_source->priv->connection);
 }
 
 static void
@@ -952,80 +604,66 @@ rb_daap_source_disconnect_cb (RBDAAPConn
 	g_object_unref (source);
 }
 
-static void
-rb_daap_source_cmd_disconnect (GtkAction *action,
-			       RBShell   *shell)
+void
+rb_daap_source_disconnect (RBDAAPSource *daap_source)
 {
-	RBSource *source;
-
-	g_object_get (shell,
-		      "selected-source", &source,
-		      NULL);
+	GSList *l;
+	RBShell *shell;
+	RhythmDB *db;
+	RhythmDBEntryType type;
 
-	if (!RB_IS_DAAP_SOURCE (source)) {
-		g_critical ("got non-Daap source for Daap action");
+	if (daap_source->priv->connection == NULL) {
 		return;
 	}
 
-	rb_daap_source_disconnect (RB_DAAP_SOURCE (source));
-
-	if (source != NULL) {
-		g_object_unref (source);
-	}
-}
-
-static void
-rb_daap_source_disconnect (RBDAAPSource *daap_source)
-{
-	if (daap_source->priv->connection) {
-		GSList *l;
-		RBShell *shell;
-		RhythmDB *db;
-		RhythmDBEntryType type;
-
-		rb_debug ("Disconnecting source");
-
-		daap_source->priv->disconnecting = TRUE;
-
-		g_object_get (daap_source, "shell", &shell, "entry-type", &type, NULL);
-		g_object_get (shell, "db", &db, NULL);
-		g_object_unref (shell);
-
-		rhythmdb_entry_delete_by_type (db, type);
-		rhythmdb_commit (db);
+	rb_debug ("Disconnecting source");
 
-		g_object_unref (db);
+	daap_source->priv->disconnecting = TRUE;
 
-		for (l = daap_source->priv->playlist_sources; l!= NULL; l = l->next) {
-			RBSource *playlist_source = RB_SOURCE (l->data);
+	g_object_get (daap_source, "shell", &shell, "entry-type", &type, NULL);
+	g_object_get (shell, "db", &db, NULL);
+	g_object_unref (shell);
 
-			rb_source_delete_thyself (playlist_source);
-		}
+	rhythmdb_entry_delete_by_type (db, type);
+	rhythmdb_commit (db);
 
-		g_slist_free (daap_source->priv->playlist_sources);
-		daap_source->priv->playlist_sources = NULL;
+	g_object_unref (db);
 
-		/* we don't want these firing while we are disconnecting */
-		g_signal_handlers_disconnect_by_func (daap_source->priv->connection,
-						      G_CALLBACK (connection_connecting_cb),
-						      daap_source);
-		g_signal_handlers_disconnect_by_func (daap_source->priv->connection,
-						      G_CALLBACK (connection_auth_cb),
-						      daap_source);
-
-		/* keep the source alive until the disconnect completes */
-		g_object_ref (daap_source);
-		rb_daap_connection_disconnect (daap_source->priv->connection,
-					       (RBDAAPConnectionCallback) rb_daap_source_disconnect_cb,
-					       daap_source);
-
-		/* wait until disconnected */
-		rb_debug ("Waiting for DAAP connection to finish");
-		while (daap_source->priv->connection != NULL) {
-			rb_debug ("Waiting for DAAP connection to finish...");
-			gtk_main_iteration ();
-		}
+	for (l = daap_source->priv->playlist_sources; l!= NULL; l = l->next) {
+		RBSource *playlist_source = RB_SOURCE (l->data);
+		char *name;
+
+		g_object_get (playlist_source, "name", &name, NULL);
+		rb_debug ("destroying DAAP playlist %s", name);
+		g_free (name);
+
+		rb_source_delete_thyself (playlist_source);
+	}
+
+	g_slist_free (daap_source->priv->playlist_sources);
+	daap_source->priv->playlist_sources = NULL;
+
+	/* we don't want these firing while we are disconnecting */
+	g_signal_handlers_disconnect_by_func (daap_source->priv->connection,
+					      G_CALLBACK (connection_connecting_cb),
+					      daap_source);
+	g_signal_handlers_disconnect_by_func (daap_source->priv->connection,
+					      G_CALLBACK (connection_auth_cb),
+					      daap_source);
+
+	/* keep the source alive until the disconnect completes */
+	g_object_ref (daap_source);
+	rb_daap_connection_disconnect (daap_source->priv->connection,
+				       (RBDAAPConnectionCallback) rb_daap_source_disconnect_cb,
+				       daap_source);
+
+	/* wait until disconnected */
+	rb_debug ("Waiting for DAAP connection to finish");
+	while (daap_source->priv->connection != NULL) {
+		rb_debug ("Waiting for DAAP connection to finish...");
+		gtk_main_iteration ();
 	}
+	rb_debug ("DAAP connection finished");
 }
 
 static gboolean
@@ -1035,44 +673,6 @@ rb_daap_source_show_popup (RBSource *sou
 	return TRUE;
 }
 
-static gboolean
-source_host_find (const char *key,
-		  RBDAAPSource *source,
-		  const char *host)
-{
-	if (source == NULL || host == NULL) {
-		return FALSE;
-	}
-
-	if (strcmp (host, source->priv->host) == 0) {
-		return TRUE;
-	}
-
-	return FALSE;
-}
-
-RBDAAPSource *
-rb_daap_source_find_for_uri (const char *uri)
-{
-	char *ip;
-	char *s;
-	RBDAAPSource *source = NULL;
-
-	if (uri == NULL) {
-		return NULL;
-	}
-
-	ip = strdup (uri + 7); /* daap:// */
-	s = strchr (ip, ':');
-	*s = '\0';
-
-	source = (RBDAAPSource *)g_hash_table_find (source_lookup, (GHRFunc)source_host_find, ip);
-
-	g_free (ip);
-
-	return source;
-}
-
 #ifdef HAVE_GSTREAMER_0_8
 char *
 rb_daap_source_get_headers (RBDAAPSource *source,
diff -rN -u -p old-daap/sources/rb-daap-source.h new-daap/sources/rb-daap-source.h
--- old-daap/sources/rb-daap-source.h	2006-11-04 20:39:02.000000000 +1000
+++ new-daap/sources/rb-daap-source.h	2006-11-04 20:39:03.000000000 +1000
@@ -24,7 +24,7 @@
 
 #include "rb-shell.h"
 #include "rb-browser-source.h"
-#include "rhythmdb.h"
+#include "rb-plugin.h"
 
 G_BEGIN_DECLS
 
@@ -47,29 +47,27 @@ typedef struct {
 	RBBrowserSourceClass parent;
 } RBDAAPSourceClass;
 
-RBSource *
-rb_daap_sources_init (RBShell *shell);
+GType 		rb_daap_source_get_type 	(void);
 
-void
-rb_daap_sources_shutdown (RBShell *shell);
+RBSource *	rb_daap_source_new 		(RBShell *shell,
+						 RBPlugin *plugin,
+						 const char *service_name,
+						 const char *name,
+						 const char *host,
+						 guint port,
+						 gboolean password_protected);
 
-GType
-rb_daap_source_get_type (void);
-
-RBDAAPSource *
-rb_daap_source_find_for_uri (const gchar *uri);
+void 		rb_daap_source_disconnect 	(RBDAAPSource *daap_source);
 
 #ifdef HAVE_GSTREAMER_0_8
-gchar *
-rb_daap_source_get_headers (RBDAAPSource *source,
-			    const gchar *uri,
-			    glong time,
-			    gint64 *bytes);
+gchar * 	rb_daap_source_get_headers 	(RBDAAPSource *source,
+					    	 const gchar *uri,
+					    	 glong time,
+					    	 gint64 *bytes);
 #else
-gchar *
-rb_daap_source_get_headers (RBDAAPSource *source,
-			    const gchar *uri, 
-			    gint64 bytes);
+gchar *		rb_daap_source_get_headers 	(RBDAAPSource *source,
+					    	 const gchar *uri,
+					    	 gint64 bytes);
 #endif
 
 G_END_DECLS

