Index: banshee/configure.ac
===================================================================
--- banshee.orig/configure.ac	2006-07-26 23:22:14.000000000 -0400
+++ banshee/configure.ac	2006-07-26 23:27:49.000000000 -0400
@@ -38,6 +38,9 @@
 AC_ARG_ENABLE(mtp, AC_HELP_STRING([--enable-mtp], [Enable MTP DAP support]), , enable_mtp="no")
 enable_mtp_dap="${enable_mtp}"
 
+AC_ARG_ENABLE(karma, AC_HELP_STRING([--enable-karma], [Enable Rio Karma DAP support]), , enable_karma="yes")
+enable_karmasharp="${enable_karma}"
+
 AC_ARG_ENABLE(docs, AC_HELP_STRING([--disable-docs], [Do not build documentation]), with_docs=no, with_docs=yes)
 
 AC_ARG_ENABLE(dev-tests, AC_HELP_STRING([--enable-dev-tests], [Whether or not to build various test programs for components in libbanshee and mediaengines]), , enable_dev_tests="no")
@@ -180,6 +183,17 @@
 fi
 AM_CONDITIONAL(ENABLE_MTP, test "x$enable_mtp_dap" = "xyes")
 
+KARMASHARP_REQUIRED=0.0.4
+PKG_CHECK_MODULES(KARMASHARP,
+	karma-sharp >= $KARMASHARP_REQUIRED,
+	enable_karmasharp="$enable_karmasharp", enable_karmasharp=no)
+if test "x$enable_karmasharp" = "xyes"; then
+	KARMASHARP_ASSEMBLIES="`$PKG_CONFIG --variable=Libraries karma-sharp`"
+	AC_SUBST(KARMASHARP_ASSEMBLIES)
+	AC_SUBST(KARMASHARP_LIBS)
+fi
+AM_CONDITIONAL(ENABLE_KARMA, test "x$enable_karmasharp" = "xyes")
+
 dnl dbus
 PKG_CHECK_MODULES(DBUSSHARP, dbus-sharp)
 AC_SUBST(DBUSSHARP)
@@ -378,6 +392,7 @@
 src/Banshee.Dap/Makefile
 src/Banshee.Dap/Ipod/Makefile
 src/Banshee.Dap/Ipod/ipod-sharp.dll.config
+src/Banshee.Dap/Karma/Makefile
 src/Banshee.Dap/MassStorage/Makefile
 src/Banshee.Dap/Mtp/Makefile
 src/Banshee.Dap/Njb/Makefile
@@ -423,6 +438,7 @@
       iPod:            ${enable_ipodsharp}
       NJB:             ${enable_njbsharp}
       MTP:             ${enable_mtp_dap}
+      Karma:           ${enable_karmasharp}
 
     DAAP Support:      ${enable_daap}${zeroconf_lib}
 "
Index: banshee/src/Banshee.Dap/Karma/Karma.cs
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ banshee/src/Banshee.Dap/Karma/Karma.cs	2006-07-29 18:46:41.000000000 -0400
@@ -0,0 +1,196 @@
+/***************************************************************************
+ *  Karma.cs
+ *
+ *  Copyright (C) 2006 Bob Copeland <me@bobcopeland.com>
+ ****************************************************************************/
+
+/*  THIS FILE IS LICENSED UNDER THE MIT LICENSE AS OUTLINED IMMEDIATELY BELOW:
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a
+ *  copy of this software and associated documentation files (the "Software"),
+ *  to deal in the Software without restriction, including without limitation
+ *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ *  and/or sell copies of the Software, and to permit persons to whom the
+ *  Software is furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in
+ *  all copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ *  DEALINGS IN THE SOFTWARE.
+ */
+
+using System;
+using System.IO;
+using System.Collections;
+using Mono.Unix;
+using Hal;
+using KarmaLib=Karma;
+using Banshee.Dap;
+using Banshee.Base;
+
+namespace Banshee.Dap.Karma
+{
+    [DapProperties(DapType = DapType.NonGeneric)]
+    [SupportedCodec(CodecType.Mp3)]
+    [SupportedCodec(CodecType.Wma)]
+    [SupportedCodec(CodecType.Ogg)]
+
+    public sealed class KarmaDap : DapDevice
+    {
+        private KarmaLib.Device device;
+        private Hal.Device hal_device;
+        private int sync_count;
+        private int sync_completed;
+        private Queue remove_queue = new Queue();
+
+        public override InitializeResult Initialize(Hal.Device halDevice)
+        {
+            if(!halDevice.PropertyExists("block.device") ||
+               !halDevice.GetPropertyBool("block.is_volume") ||
+               !IsKarma(halDevice)) {
+                return InitializeResult.Invalid;
+            } else if(!halDevice.GetPropertyBool("volume.is_mounted")) {
+                return InitializeResult.WaitForPropertyChange;
+            }
+
+            hal_device = halDevice;
+
+            if (LoadKarma() == InitializeResult.Invalid) {
+                return InitializeResult.Invalid;
+            }
+
+            ReloadDatabase();
+
+            base.Initialize(halDevice);
+            return InitializeResult.Valid;
+        }
+
+        private bool IsKarma(Hal.Device halDevice)
+        {
+            return halDevice["block.storage_device"].IndexOf("Rio_Karma") >= 0;
+        }
+
+        private InitializeResult LoadKarma() {
+            try {
+                device = new KarmaLib.Device(hal_device["volume.mount_point"]);
+            } catch(Exception e) {
+                return InitializeResult.Invalid;
+            }
+            return InitializeResult.Valid;
+        }
+
+        public override Gdk.Pixbuf GetIcon(int size)
+        {
+            Gdk.Pixbuf icon = IconThemeUtils.LoadIcon(
+                    "multimedia-player-rio-karma", size);
+            if (icon != null) {
+                return icon;
+            }
+
+            return base.GetIcon(size);
+        }
+
+        private void ReloadDatabase()
+        {
+            ClearTracks(false);
+            foreach (KarmaLib.Song song in device.GetSongs()) {
+                KarmaDapTrackInfo track = new KarmaDapTrackInfo(song,
+                    hal_device["volume.mount_point"]);
+                AddTrack(track);
+            }
+        }
+
+        public override void AddTrack(TrackInfo track) {
+            if (track is KarmaDapTrackInfo ||
+                !TrackExistsInList(track, Tracks)) {
+                tracks.Add(track);
+                OnTrackAdded(track);
+            }
+        }
+
+        protected override void OnTrackRemoved(TrackInfo track) {
+            if (!(track is KarmaDapTrackInfo))
+                return;
+            remove_queue.Enqueue(track);
+        }
+
+        public override void Synchronize()
+        {
+            sync_count = 0;
+            sync_completed = 0;
+
+            int remove_total = remove_queue.Count;
+
+            while (remove_queue.Count > 0) {
+                KarmaDapTrackInfo track = remove_queue.Dequeue() as
+                    KarmaDapTrackInfo;
+                UpdateSaveProgress(Catalog.GetString("Synchronizing Device"),
+                    Catalog.GetString("Removing Songs"),
+                    (double) (remove_total - remove_queue.Count) /
+                    (double) remove_total);
+                device.DeleteSong(track.TrackId);
+            }
+
+            foreach (TrackInfo track in Tracks) {
+                if (track is KarmaDapTrackInfo)
+                    continue;
+
+                if (track.Uri.IsFile) {
+                    device.QueueAddSong(track.Uri.LocalPath);
+                    sync_count++;
+                }
+            }
+            device.ProgressChanged += OnFileUploaded;
+            device.Save();
+            ReloadDatabase();
+            FinishSave();
+        }
+
+        private void OnFileUploaded(KarmaLib.Song song)
+        {
+            sync_completed++;
+            string message = String.Format("{0} - {1}", song.Artist,
+                song.Title);
+
+            UpdateSaveProgress(Catalog.GetString("Synchronizing Device"),
+                message, (double)sync_completed/(double)sync_count);
+        }
+
+        public override string Name {
+            get {
+                return "Karma";
+            }
+        }
+
+        public override ulong StorageCapacity {
+            get {
+                return device.GetStorageDetails().StorageSize;
+            }
+        }
+
+        public override ulong StorageUsed {
+            get {
+                KarmaLib.StorageDetails details = device.GetStorageDetails();
+                return details.StorageSize - details.FreeSpace;
+            }
+        }
+
+        public override bool IsReadOnly {
+            get {
+                return false;
+            }
+        }
+
+        public override bool IsPlaybackSupported {
+            get {
+                return false;
+            }
+        }
+    }
+}
Index: banshee/src/Banshee.Dap/Karma/KarmaDapTrackInfo.cs
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ banshee/src/Banshee.Dap/Karma/KarmaDapTrackInfo.cs	2006-07-29 18:46:25.000000000 -0400
@@ -0,0 +1,30 @@
+using System;
+using KarmaLib=Karma;
+using Banshee.Base;
+using Banshee.Dap;
+
+namespace Banshee.Dap.Karma
+{
+    public sealed class KarmaDapTrackInfo : DapTrackInfo
+    {
+        public KarmaDapTrackInfo(KarmaLib.Song song, string mount)
+        {
+            /*
+            string fidstr = String.Format("{0:x8}", song.Id);
+            uri = new SafeUri(String.Format("file://{0}/fids0/_{1}/{2}", mount,
+                fidstr.Substring(0,5), fidstr.Substring(5)));
+            */
+            album = song.Album;
+            artist = song.Artist;
+            title = song.Title;
+            genre = song.Genre;
+            track_id = song.Id;
+            duration = new TimeSpan(song.Duration * 1000L);
+            play_count = song.PlayCount;
+            last_played = song.LastPlayed;
+            track_count = 0;
+            track_number = song.TrackNumber;
+            year = song.Year;
+        }
+    }
+}
Index: banshee/src/Banshee.Dap/Karma/Makefile.am
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ banshee/src/Banshee.Dap/Karma/Makefile.am	2006-07-26 23:27:49.000000000 -0400
@@ -0,0 +1,34 @@
+MCS_FLAGS = -debug
+ASSEMBLY_NAME = Banshee.Dap.Karma
+ASSEMBLY = $(ASSEMBLY_NAME).dll
+
+CLEANFILES = $(ASSEMBLY) *.dll *.exe
+DISTCLEANFILES = *.mdb
+MAINTAINERCLEANFILES = Makefile.in
+
+ASSEMBLY_SOURCES = \
+	$(srcdir)/Karma.cs \
+	$(srcdir)/KarmaDapTrackInfo.cs
+
+if ENABLE_KARMA
+
+bansheedapdir = $(pkglibdir)/Banshee.Dap
+bansheedap_SCRIPTS = $(ASSEMBLY) $(ASSEMBLY).mdb karma-sharp.dll.config
+
+endif
+
+$(ASSEMBLY): $(ASSEMBLY_SOURCES)
+	$(MCS) $(MCS_FLAGS) -target:library -out:$@ -r:$(top_builddir)/src/Banshee.Base/Banshee.Base.dll -r:$(top_builddir)/src/Banshee.Widgets/Banshee.Widgets.dll -r:$(top_builddir)/hal-sharp/hal-sharp.dll -r:Mono.Posix -r:$(top_builddir)/entagged-sharp/entagged-sharp.dll $(GTKSHARP_LIBS) $(KARMASHARP_LIBS) $(ASSEMBLY_SOURCES)
+
+EXTRA_DIST = $(ASSEMBLY_SOURCES) karma-sharp.dll.config
+
+install-data-hook:
+	for ASM in $(KARMASHARP_ASSEMBLIES); do \
+		$(INSTALL) -m 0755 $$ASM $(DESTDIR)$(bansheedapdir); \
+	done;
+
+uninstall-hook:
+	for ASM in $(KARMASHARP_ASSEMBLIES); do \
+		rm -f $(DESTDIR)$(bansheedapdir)/`basename $$ASM`; \
+	done;
+
Index: banshee/src/Banshee.Dap/Karma/karma-sharp.dll.config
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ banshee/src/Banshee.Dap/Karma/karma-sharp.dll.config	2006-07-26 23:27:49.000000000 -0400
@@ -0,0 +1,4 @@
+<configuration>
+	<dllmap dll="karma" target="libkarma.so" />
+</configuration>
+
Index: banshee/src/Banshee.Dap/Makefile.am
===================================================================
--- banshee.orig/src/Banshee.Dap/Makefile.am	2006-07-26 23:22:14.000000000 -0400
+++ banshee/src/Banshee.Dap/Makefile.am	2006-07-26 23:27:49.000000000 -0400
@@ -1,4 +1,4 @@
-SUBDIRS = Ipod MassStorage Mtp Njb
+SUBDIRS = Ipod MassStorage Karma Mtp Njb
 
 MAINTAINERCLEANFILES = Makefile.in
 
