diff --git a/configure.in b/configure.in
index 9577162..30e0bec 100644
--- a/configure.in
+++ b/configure.in
@@ -68,7 +68,7 @@ AC_SUBST(TOTEM_API_VERSION)
 AC_DEFINE_UNQUOTED(TOTEM_API_VERSION, ["$TOTEM_API_VERSION"], [Define to the Totem plugin API version])
 
 # The full list of plugins
-allowed_plugins="bemused brasero-disc-recorder chapters coherence_upnp dbusservice im-status gromit iplayer jamendo lirc media-player-keys ontop opensubtitles properties publish pythonconsole save-file samplepython sample-vala screensaver screenshot sidebar-test skipto tracker youtube zeitgeist-dp"
+allowed_plugins="bemused brasero-disc-recorder chapters coherence_upnp daap dbusservice im-status gromit iplayer jamendo lirc media-player-keys ontop opensubtitles properties publish pythonconsole save-file samplepython sample-vala screensaver screenshot sidebar-test skipto tracker youtube zeitgeist-dp"
 
 PLUGINDIR='${libdir}/totem/plugins'
 AC_SUBST(PLUGINDIR)
@@ -394,6 +394,14 @@ for plugin in ${used_plugins}; do
 			plugin_error_or_ignore "the coherence_upnp plugin uses PyGTK and conflicts with the new pygobject bindings"
 			add_plugin="0"
 		;;
+		daap)
+			PKG_CHECK_MODULES(DAAP, libdmapsharing-3.0 >= 2.9.12 libsoup-2.4 gstreamer-0.10,
+					  [BUILD_DAAP=yes], [BUILD_DAAP=no])
+			if test "${BUILD_DAAP}" != "yes" ; then
+				plugin_error_or_ignore "you need libdmapsharing-3.0 >= 2.9.12 to use the DAAP plugin"
+				add_plugin="0"
+			fi
+		;;
 		gromit)
 			if test "${have_x11}" != "yes" ; then
 				plugin_error_or_ignore "the gromit plugin is not supported on non-X11 targets"
@@ -743,6 +751,7 @@ src/properties/Makefile
 src/plugins/Makefile
 src/plugins/bemused/Makefile
 src/plugins/coherence_upnp/Makefile
+src/plugins/daap/Makefile
 src/plugins/dbusservice/Makefile
 src/plugins/screensaver/Makefile
 src/plugins/screenshot/Makefile
diff --git a/src/plugins/daap/Makefile.am b/src/plugins/daap/Makefile.am
index e69de29..2adc559 100644
--- a/src/plugins/daap/Makefile.am
+++ b/src/plugins/daap/Makefile.am
@@ -0,0 +1,28 @@
+include $(top_srcdir)/src/plugins/Makefile.plugins
+
+plugindir = $(PLUGINDIR)/daap
+plugin_LTLIBRARIES = libdaap.la
+
+plugin_in_files = daap.plugin.in
+
+# here we are explicitly specifying gtk+-3.0 to use the vapi because vala still
+# cannot parse the gir
+VALAFLAGS =                        \
+	--girdir=$(top_srcdir)/src \
+	--pkg Totem-1.0            \
+	--pkg Peas-1.0             \
+	--pkg gtk+-3.0             \
+	--pkg libdmapsharing-3.0   \
+	--pkg libsoup-2.4          \
+	--pkg gstreamer-0.10
+
+libdaap_la_SOURCES = totem-daap-plugin.vala
+libdaap_la_LDFLAGS = $(plugin_ldflags)
+libdaap_la_CFLAGS = $(plugin_cflags) $(DAAP_CFLAGS)
+libdaap_la_LIBADD = $(plugin_libadd) $(DAAP_LIBS)
+
+uidir = $(plugindir)
+ui_DATA = daap.ui
+EXTRA_DIST += $(ui_DATA)
+
+-include $(top_srcdir)/git.mk
diff --git a/src/plugins/daap/daap.plugin.in b/src/plugins/daap/daap.plugin.in
index e69de29..377ae0b 100644
--- a/src/plugins/daap/daap.plugin.in
+++ b/src/plugins/daap/daap.plugin.in
@@ -0,0 +1,8 @@
+[Plugin]
+Module=daap
+IAge=1
+_Name=DAAP Browser
+_Description=A plugin to let you browse DAAP shares.
+Authors=W. Michael Petullo <mike@flyn.org>
+Copyright=Copyright © 2011 W. Michael Petullo
+Website=http://www.gnome.org/projects/totem/
diff --git a/src/plugins/daap/daap.ui b/src/plugins/daap/daap.ui
index e69de29..0000e8d 100644
--- a/src/plugins/daap/daap.ui
+++ b/src/plugins/daap/daap.ui
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<!--*- mode: xml -*-->
+<interface>
+
+<object class="GtkTreeStore" id="daap_video_store">
+	<columns>
+		<column type="gchararray"/> <!-- Video title -->
+		<column type="gchararray"/> <!-- Video location -->
+	</columns>
+</object>
+
+<object class="GtkVBox" id="daap_vbox">
+	<property name="border-width">5</property>
+	<property name="homogeneous">False</property>
+	<property name="spacing">6</property>
+	<child>
+		<object class="GtkScrolledWindow" id="daap_scrolled_window">
+			<property name="hscrollbar-policy">GTK_POLICY_AUTOMATIC</property>
+			<property name="vscrollbar-policy">GTK_POLICY_AUTOMATIC</property>
+			<property name="shadow-type">GTK_SHADOW_IN</property>
+			<child>
+				<object class="GtkTreeView" id="daap_video_list">
+					<property name="model">daap_video_store</property>
+					<property name="expander-column">daap_title_column</property>
+					<property name="headers-visible">False</property>
+					<child>
+						<object class="GtkTreeViewColumn" id="daap_title_column">
+							<child>
+								<object class="GtkCellRendererText" id="daap_title_cell_renderer"/>
+								<attributes>
+									<attribute name="text">0</attribute>
+								</attributes>
+							</child>
+						</object>
+					</child>
+				</object>
+			</child>
+		</object>
+	</child>
+</object>
+
+</interface>
diff --git a/src/plugins/daap/totem-daap-plugin.vala b/src/plugins/daap/totem-daap-plugin.vala
index e69de29..a7785cc 100644
--- a/src/plugins/daap/totem-daap-plugin.vala
+++ b/src/plugins/daap/totem-daap-plugin.vala
@@ -0,0 +1,160 @@
+// A DAAP video plugin for Totem. This plugin ignores media that does not have
+// a video component.
+class DAAPPlugin: GLib.Object, Peas.Activatable {
+	public Totem.Object object { get; set; }
+
+	private Gtk.TreeStore store;
+	private DMAP.MdnsBrowser browser;
+	private TotemDMAPDb db;
+	private TotemDAAPRecordFactory factory;
+
+	public void activate () {
+		var builder = Totem.plugin_load_interface ("daap", "daap.ui", true, object.get_main_window (), null);
+		var container = builder.get_object ("daap_vbox") as Gtk.Container;
+		var list = builder.get_object ("daap_video_list") as Gtk.TreeView;
+		store = builder.get_object ("daap_video_store") as Gtk.TreeStore;
+
+		list.row_activated.connect ((view, path, column) => {
+			var store = view.get_model ();
+
+			Gtk.TreeIter iter;
+			store.get_iter (out iter, path);
+
+			GLib.Value title, location;
+			store.get_value (iter, 0, out title);
+			store.get_value (iter, 1, out location);
+
+			// Replace "daap://..." with "http://..."
+			var http_location = "http" + ((string) location).substring(4);
+			object.add_to_playlist_and_play (http_location, (string) title, true);
+		});
+
+		container.show_all ();
+
+		object.add_sidebar_page ("daap", "DAAP Browser", container);
+
+		browser = new DMAP.MdnsBrowser (DMAP.MdnsBrowserServiceType.DAAP);
+		browser.service_added.connect (service_added_cb);
+		browser.start ();
+	}
+
+	public void deactivate () {
+		object.remove_sidebar_page ("daap");
+		browser.stop ();
+	}
+
+	public void update_state () {}
+
+	private bool connected_cb (DMAP.Connection connection, bool result, string? reason) {
+		return true;
+	}
+
+	private void service_added_cb (DMAP.MdnsBrowserService *service) {
+		db = new TotemDMAPDb (store);
+		factory = new TotemDAAPRecordFactory ();
+		DMAP.Connection connection = (DMAP.Connection) new DAAP.Connection (service->service_name,
+		                                                                    service->host,
+										    service->port,
+										    db,
+										    factory);
+
+		connection.connect (connected_cb);
+	}
+}
+
+// A DAAPRecord implementation.
+private class TotemDAAPRecord : GLib.Object, DMAP.Record, DAAP.Record {
+	public string location { get; set; }
+	public string title { get; set; }
+	public int rating { get; set; }
+	public int filesize { get; set; }
+	public string album { get; set; }
+	public string artist { get; set; }
+	public string genre { get; set; }
+	public string format { get; set; }
+	public int duration { get; set; }
+	public int track { get; set; }
+	public int year { get; set; }
+	public int firstseen { get; set; }
+	public int mtime { get; set; }
+	public int disc { get; set; }
+	public ulong bitrate { get; set; }
+	public bool has_video { get; set; }
+
+	public unowned GLib.InputStream read () throws GLib.Error {
+		GLib.error ("read not implemented");
+	}
+
+	public unowned DMAP.Record set_from_blob (GLib.ByteArray blob) {
+		GLib.error ("set_from_blob not implemented");
+	}
+
+	public unowned GLib.ByteArray to_blob () {
+		GLib.error ("to_blob not implemented");
+	}
+
+	public bool itunes_compat () {
+		GLib.error ("itunes_compat not implemented");
+	}
+}
+
+// A DAAPRecordFactory implementation.
+private class TotemDAAPRecordFactory : GLib.Object, DMAP.RecordFactory {
+	public DMAP.Record create (void* user_data) {
+		return new TotemDAAPRecord ();
+	}
+}
+
+// A DMAPDb implementation. A severely handicapped database; only stores title & location
+// (yes, this is DAAP-specific) and only if the record has a video component; database is
+// the GUI's Gtk.TreeStore store.
+private class TotemDMAPDb : GLib.Object, DMAP.Db {
+	private Gtk.TreeStore store;
+	private uint id = 0;
+
+	public uint add (DMAP.Record record) {
+		if (((TotemDAAPRecord) record).has_video) {
+			Gtk.TreeIter iter;
+			store.append (out iter, null);
+			// NOTE: cast to DAAP, but interface is DMAP:
+			store.set (iter, 0, ((TotemDAAPRecord) record).title, 1, ((TotemDAAPRecord) record).location);
+		}
+
+		// NOTE: ID is irrelevent for this use case.
+		return id++;
+	}
+
+	public uint add_path (string path) {
+		GLib.error ("add_path not implemented");
+	}
+
+	public uint add_with_id (DMAP.Record record, uint id) {
+		GLib.error ("add_with_id not implemented");
+	}
+
+	public int64 count () {
+		return store.iter_n_children (null);
+	}
+
+	public void @foreach (GLib.HFunc func) {
+		GLib.error ("foreach not implemented");
+	}
+
+	public unowned DMAP.Record lookup_by_id (uint id) {
+		GLib.error ("lookup_by_id not implemented");
+	}
+
+	public uint lookup_id_by_location (string location){
+		GLib.error ("lookup_id_by_location not implemented");
+	}
+
+	public TotemDMAPDb (Gtk.TreeStore s) {
+		store = s;
+	}
+}
+
+[ModuleInit]
+public void peas_register_types (GLib.TypeModule module) {
+	var objmodule = module as Peas.ObjectModule;
+	objmodule.register_extension_type (typeof (Peas.Activatable), typeof (DAAPPlugin));
+}
