[banshee] [Hardware.Gio] First pass at GIO/udev HardwareManager



commit a3dc5844e08c9e010e8ddfc9004d2fe1a215496f
Author: Alex Launi <alex launi gmail com>
Date:   Fri Jul 16 17:42:15 2010 -0700

    [Hardware.Gio] First pass at GIO/udev HardwareManager
    
    Since HAL is obsolete, this backend will replace our existing HAL-based
    HardwareManager backend on distros where HAL is no longer shipped.  It
    is not complete or usable as of this commit, but should be soon.
    
    Signed-off-by: Gabriel Burt <gabriel burt gmail com>

 build/build.environment.mk                         |    4 +-
 build/m4/banshee/gio.m4                            |   28 +++
 build/m4/banshee/hal.m4                            |    6 +
 configure.ac                                       |   13 +-
 data/addin-xml-strings.cs                          |    2 +-
 src/Backends/Banshee.Gio/Banshee.Gio.addin.xml     |    7 +-
 src/Backends/Banshee.Gio/Banshee.Gio.csproj        |   60 ++++-
 .../Banshee.Hardware.Gio/BlockDevice.cs            |  101 ++++++++
 .../Banshee.Hardware.Gio/CdromDevice.cs            |  104 ++++++++
 .../Banshee.Gio/Banshee.Hardware.Gio/Device.cs     |  123 ++++++++++
 .../DeviceMediaCapabilities.cs                     |  241 +++++++++++++++++++
 .../Banshee.Gio/Banshee.Hardware.Gio/DiscVolume.cs |   83 +++++++
 .../Banshee.Gio/Banshee.Hardware.Gio/DiskDevice.cs |   58 +++++
 .../Banshee.Hardware.Gio/HardwareManager.cs        |  126 ++++++++++
 .../LowLevel/GioDriveMetadetaSource.cs             |   81 +++++++
 .../LowLevel/GioMetadataSource.cs                  |   52 ++++
 .../LowLevel/GioVolumeMetadataSource.cs            |   80 ++++++
 .../LowLevel/IMetadataSource.cs                    |   42 ++++
 .../Banshee.Hardware.Gio/LowLevel/IRawDevice.cs    |   38 +++
 .../Banshee.Hardware.Gio/LowLevel/Manager.cs       |  240 ++++++++++++++++++
 .../LowLevel/RawBlockDevice.cs                     |  164 +++++++++++++
 .../Banshee.Hardware.Gio/LowLevel/RawDevice.cs     |  146 +++++++++++
 .../Banshee.Hardware.Gio/LowLevel/RawVolume.cs     |  254 ++++++++++++++++++++
 .../LowLevel/UdevMetadataSource.cs                 |  110 +++++++++
 .../Banshee.Gio/Banshee.Hardware.Gio/UsbDevice.cs  |  189 +++++++++++++++
 .../Banshee.Gio/Banshee.Hardware.Gio/UsbVolume.cs  |   78 ++++++
 .../Banshee.Gio/Banshee.Hardware.Gio/Volume.cs     |  106 ++++++++
 src/Backends/Banshee.Gio/Makefile.am               |   24 ++
 .../Banshee.Hal/Banshee.HalBackend/UsbDevice.cs    |    8 +
 src/Backends/Banshee.Hal/Hal/Manager.cs            |    7 +-
 src/Backends/Banshee.Hal/Makefile.am               |    4 +
 src/Backends/Makefile.am                           |    2 +-
 .../Banshee.Hardware/HardwareManager.cs            |    2 +-
 .../Banshee.Hardware/IUsbDevice.cs                 |    2 +
 34 files changed, 2566 insertions(+), 19 deletions(-)
---
diff --git a/build/build.environment.mk b/build/build.environment.mk
index 76f6257..7c4eeb2 100644
--- a/build/build.environment.mk
+++ b/build/build.environment.mk
@@ -17,6 +17,8 @@ LINK_GLIB = $(GLIBSHARP_LIBS)
 LINK_GTK = $(GTKSHARP_LIBS)
 LINK_GCONF = $(GCONFSHARP_LIBS)
 LINK_GIO = $(GTKSHARP_BEANS_LIBS) $(GIOSHARP_LIBS)
+LINK_GKEYFILE = $(GKEYFILE_SHARP_LIBS)
+LINK_GUDEV = $(GUDEV_SHARP_LIBS)
 LINK_DBUS = $(NDESK_DBUS_LIBS) $(NDESK_DBUS_GLIB_LIBS)
 LINK_DBUS_NO_GLIB = $(NDESK_DBUS_LIBS) 
 LINK_TAGLIB = $(TAGLIB_SHARP_LIBS)
@@ -159,7 +161,7 @@ REF_EXTENSION_REMOTE_AUDIO = $(LINK_BANSHEE_THICKCLIENT_DEPS) $(LINK_MONO_ZEROCO
 REF_EXTENSION_WIKIPEDIA= $(LINK_BANSHEE_WEBBROWSER_DEPS)
 
 # Backends
-REF_BACKEND_GIO = $(LINK_BANSHEE_SERVICES_DEPS) $(LINK_GIO)
+REF_BACKEND_GIO = $(LINK_BANSHEE_SERVICES_DEPS) $(LINK_GIO) $(LINK_GUDEV) $(LINK_GKEYFILE)
 REF_BACKEND_GNOME = $(LINK_BANSHEE_SERVICES_DEPS) $(LINK_BANSHEE_THICKCLIENT_DEPS) $(LINK_GCONF)
 REF_BACKEND_GSTREAMER = $(LINK_BANSHEE_SERVICES_DEPS) $(LINK_GLIB)
 REF_BACKEND_UNIX = $(LINK_BANSHEE_CORE_DEPS) $(LINK_MONO_POSIX)
diff --git a/build/m4/banshee/gio.m4 b/build/m4/banshee/gio.m4
index 4d39d9d..75cbd3f 100644
--- a/build/m4/banshee/gio.m4
+++ b/build/m4/banshee/gio.m4
@@ -3,6 +3,7 @@ AC_DEFUN([BANSHEE_CHECK_GIO_SHARP],
 	GNOMESHARP_REQUIRED=2.8
 	
 	AC_ARG_ENABLE(gio, AC_HELP_STRING([--disable-gio], [Disable GIO for IO operations]), ,enable_gio="yes")
+	AC_ARG_ENABLE(gio_hardware, AC_HELP_STRING([--disable-gio-hardware], [Disable GIO Hardware backend]), ,enable_gio_hardware="yes")
 	
 	if test "x$enable_gio" = "xyes"; then
 	   	PKG_CHECK_MODULES(GTKSHARP_BEANS,
@@ -17,9 +18,36 @@ AC_DEFUN([BANSHEE_CHECK_GIO_SHARP],
 			glib-2.0 >= 2.22,
 			enable_gio="$enable_gio", enable_gio=no)
 
+		if test "x$enable_gio_hardware" = "xyes"; then
+            PKG_CHECK_MODULES(GUDEV_SHARP,
+                gudev-sharp-1.0 >= 0.1,
+                enable_gio_hardware="$enable_gio", enable_gio_hardware=no)
+
+            PKG_CHECK_MODULES(GKEYFILE_SHARP,
+                gkeyfile-sharp-1.0 >= 0.1,
+                enable_gio_hardware="$enable_gio_hardware", enable_gio_hardware=no)
+
+            if test "x$enable_gio_hardware" = "xyes"; then
+                asm="`$PKG_CONFIG --variable=Libraries gkeyfile-sharp-1.0`"
+                GIOSHARP_ASSEMBLIES="$GIOSHARP_ASSEMBLIES $asm $asm.config"
+                asm="`$PKG_CONFIG --variable=Libraries gudev-sharp-1.0`"
+                GIOSHARP_ASSEMBLIES="$GIOSHARP_ASSEMBLIES $asm $asm.config"
+                AC_SUBST(GIOSHARP_ASSEMBLIES)
+            fi
+        fi
+
+		if test "x$enable_gio" = "xyes"; then
+			asm="`$PKG_CONFIG --variable=Libraries gio-sharp-2.0`"
+			GIOSHARP_ASSEMBLIES="$GIOSHARP_ASSEMBLIES $asm $asm.config"
+			AC_SUBST(GIOSHARP_ASSEMBLIES)
+		fi
+
 		AM_CONDITIONAL(ENABLE_GIO, test "x$enable_gio" = "xyes")
+		AM_CONDITIONAL(ENABLE_GIO_HARDWARE, test "x$enable_gio_hardware" = "xyes")
 	else
+        enable_gio_hardware="no"
 		AM_CONDITIONAL(ENABLE_GIO, false)
+		AM_CONDITIONAL(ENABLE_GIO_HARDWARE, false)
 	fi
 ])
 
diff --git a/build/m4/banshee/hal.m4 b/build/m4/banshee/hal.m4
new file mode 100644
index 0000000..a9c4753
--- /dev/null
+++ b/build/m4/banshee/hal.m4
@@ -0,0 +1,6 @@
+AC_DEFUN([BANSHEE_CHECK_HAL],
+[
+	AC_ARG_ENABLE(hal, AC_HELP_STRING([--disable-hal], [Disable Hal hardware backend]), ,enable_hal="yes")
+
+	AM_CONDITIONAL(ENABLE_HAL, test "x$enable_hal" = "xyes")
+])
\ No newline at end of file
diff --git a/configure.ac b/configure.ac
index 509eb97..5b91923 100644
--- a/configure.ac
+++ b/configure.ac
@@ -120,6 +120,9 @@ BANSHEE_CHECK_LIBWEBKIT
 dnl gdata (optional through --disable-youtube)
 BANSHEE_CHECK_YOUTUBE
 
+dnl Check for disabled hal
+BANSHEE_CHECK_HAL
+
 dnl gtk#-beans and gio#
 BANSHEE_CHECK_GIO_SHARP
 
@@ -402,16 +405,18 @@ ${PACKAGE}-${VERSION}
     Builtin Equalizer: ${enable_builtin_equalizer}
     DAAP:              ${enable_daap}
     GIO Backend:       ${enable_gio} (glib >= 2.22, gtk-sharp-beans, and gio-sharp)
+    GIO Hardware:      ${enable_gio_hardware} (gudev-sharp, gkeyfile-sharp)
+    HAL Backend:       ${enable_hal}
     Library Watcher:   ${HAVE_MONO_2_4_3} (Mono >= 2.4.3)
     Podcasts:          ${enable_podcast}
     Gapless playback:  ${ENABLE_GAPLESS} (gstreamer-plugins-base > 0.10.25.2)
     YouTube extension: ${enable_youtube} (gdata-sharp >= 1.4)
 
   Build/Development:
-    Unit Tests:        ${do_tests} (requires nunit >= ${NUNIT_REQUIRED})
-    API Docs:          ${enable_docs} (requires monodocer and mdassembler)
-    User Help:         ${enable_user_help} (requires gnome-doc-utils >= 0.17.3)
-    Custom a11y:       ${gtksharp_with_a11y} (requires gtk-sharp >= 2.12.10)
+    Unit Tests:        ${do_tests} (nunit >= ${NUNIT_REQUIRED})
+    API Docs:          ${enable_docs} (monodocer and mdassembler)
+    User Help:         ${enable_user_help} (gnome-doc-utils >= 0.17.3)
+    Custom a11y:       ${gtksharp_with_a11y} (gtk-sharp >= 2.12.10)
     Release Build:     ${enable_release}
     Vendor Build ID:   ${vendor_build_id}
 
diff --git a/data/addin-xml-strings.cs b/data/addin-xml-strings.cs
index a45414a..e81fc34 100644
--- a/data/addin-xml-strings.cs
+++ b/data/addin-xml-strings.cs
@@ -5,7 +5,7 @@ internal static class AddinXmlStringCatalog
     private static void Strings ()
     {
         // ../src/Backends/Banshee.Gio/Banshee.Gio.addin.xml
-        Catalog.GetString (@"GIO IO backend");
+        Catalog.GetString (@"GIO IO and Hardware backends");
 
         // ../src/Backends/Banshee.Gnome/Banshee.Gnome.addin.xml
         Catalog.GetString (@"Backend providers for the GNOME platform. Includes GConf support and general GNOME integration.");
diff --git a/src/Backends/Banshee.Gio/Banshee.Gio.addin.xml b/src/Backends/Banshee.Gio/Banshee.Gio.addin.xml
index 8faf806..142a8ab 100644
--- a/src/Backends/Banshee.Gio/Banshee.Gio.addin.xml
+++ b/src/Backends/Banshee.Gio/Banshee.Gio.addin.xml
@@ -5,14 +5,19 @@
     compatVersion="1.0"
     copyright="© 2009 Novell Inc. Licensed under the MIT X11 license."
     category="required:Backends"
-    description="GIO IO backend"
+    description="GIO IO and Hardware backends"
     defaultEnabled="true">
 
   <Dependencies>
     <Addin id="Banshee.Core" version="1.0"/>
+    <Addin id="Banshee.Services" version="1.0"/>
   </Dependencies>
   
   <Extension path="/Banshee/Platform/IOProvider">
     <IOProvider class="Banshee.IO.Gio.Provider" id="Banshee.IO.Gio.Provider" />
   </Extension>
+  
+  <Extension path="/Banshee/Platform/HardwareManager">
+    <HardwareManager class="Banshee.Hardware.Gio.HardwareManager" id="Banshee.Hardware.Gio" />
+  </Extension>
 </Addin>
diff --git a/src/Backends/Banshee.Gio/Banshee.Gio.csproj b/src/Backends/Banshee.Gio/Banshee.Gio.csproj
index 820cc7e..46fcac1 100644
--- a/src/Backends/Banshee.Gio/Banshee.Gio.csproj
+++ b/src/Backends/Banshee.Gio/Banshee.Gio.csproj
@@ -65,15 +65,18 @@
   </ItemGroup>
   <ItemGroup>
     <Reference Include="System" />
-    <Reference Include="System.Core" />
-    <Reference Include="gtk-sharp">
-      <SpecificVersion>False</SpecificVersion>
+    <Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
+      <Package>gtk-sharp-2.0</Package>
     </Reference>
-    <Reference Include="glib-sharp">
-      <SpecificVersion>False</SpecificVersion>
+    <Reference Include="gnome-sharp, Version=2.24.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
+      <Package>gnome-sharp-2.0</Package>
     </Reference>
-    <Reference Include="gio-sharp">
-      <SpecificVersion>False</SpecificVersion>
+    <Reference Include="System.Core">
+    </Reference>
+    <Reference Include="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
+      <Package>glib-sharp-2.0</Package>
+    </Reference>
+    <Reference Include="gio-sharp, Version=2.14.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
       <HintPath>..\..\..\bin\gio-sharp.dll</HintPath>
     </Reference>
     <Reference Include="gtk-sharp-beans">
@@ -83,6 +86,25 @@
     <Reference Include="taglib-sharp">
       <SpecificVersion>False</SpecificVersion>
       <HintPath>..\..\..\bin\taglib-sharp.dll</HintPath>
+      <Package>taglib-sharp</Package>
+    </Reference>
+    <Reference Include="libgudev, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3565e728cafab25e">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\..\gudev-sharp\gudev\libgudev.dll</HintPath>
+    </Reference>
+    <Reference Include="gio-sharp, Version=2.14.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
+      <HintPath>..\..\..\..\..\..\..\usr\local\lib\mono\gio-sharp-2.0\gio-sharp.dll</HintPath>
+      <SpecificVersion>False</SpecificVersion>
+    </Reference>
+    <Reference Include="Mono.Posix" />
+    <Reference Include="Nini, Version=1.1.0.0, Culture=neutral, PublicKeyToken=c9892194e1b9ec1b">
+      <Package>nini-1.1</Package>
+    </Reference>
+    <Reference Include="gio-sharp, Version=0.0.0.0, Culture=neutral">
+    </Reference>
+    <Reference Include="gkeyfile-sharp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e886e4e52ee77480">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\..\..\..\..\usr\local\lib\mono\gkeyfile-sharp-1.0\gkeyfile-sharp.dll</HintPath>
     </Reference>
   </ItemGroup>
   <ItemGroup>
@@ -91,6 +113,26 @@
     <Compile Include="Banshee.IO.Gio\File.cs" />
     <Compile Include="Banshee.IO.Gio\Provider.cs" />
     <Compile Include="Banshee.IO.Gio\Tests.cs" />
+    <Compile Include="Banshee.GioBackend\HardwareManager.cs" />
+    <Compile Include="LowLevel\Manager.cs" />
+    <Compile Include="Banshee.GioBackend\Volume.cs" />
+    <Compile Include="Banshee.GioBackend\BlockDevice.cs" />
+    <Compile Include="Banshee.GioBackend\CdromDevice.cs" />
+    <Compile Include="Banshee.GioBackend\Device.cs" />
+    <Compile Include="Banshee.GioBackend\DeviceMediaCapabilities.cs" />
+    <Compile Include="Banshee.GioBackend\DiscVolume.cs" />
+    <Compile Include="Banshee.GioBackend\DiskDevice.cs" />
+    <Compile Include="Banshee.GioBackend\UsbDevice.cs" />
+    <Compile Include="LowLevel\IMetadataSource.cs" />
+    <Compile Include="LowLevel\UdevMetadataSource.cs" />
+    <Compile Include="LowLevel\GioVolumeMetadataSource.cs" />
+    <Compile Include="LowLevel\IRawDevice.cs" />
+    <Compile Include="LowLevel\RawDevice.cs" />
+    <Compile Include="LowLevel\RawVolume.cs" />
+    <Compile Include="LowLevel\RawBlockDevice.cs" />
+    <Compile Include="LowLevel\GioMetadataSource.cs" />
+    <Compile Include="LowLevel\GioDriveMetadetaSource.cs" />
+    <Compile Include="Banshee.GioBackend\UsbVolume.cs" />
   </ItemGroup>
   <ItemGroup>
     <EmbeddedResource Include="Banshee.Gio.addin.xml">
@@ -113,4 +155,8 @@
       </Properties>
     </MonoDevelop>
   </ProjectExtensions>
+  <ItemGroup>
+    <Folder Include="Banshee.GioBackend\" />
+    <Folder Include="LowLevel\" />
+  </ItemGroup>
 </Project>
diff --git a/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/BlockDevice.cs b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/BlockDevice.cs
new file mode 100644
index 0000000..a642844
--- /dev/null
+++ b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/BlockDevice.cs
@@ -0,0 +1,101 @@
+//
+// BlockDevice.cs
+//
+// Author:
+//   Alex Launi <alex launi gmail com>
+//
+// Copyright (c) 2010 Alex Launi
+//
+// 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.
+
+#if ENABLE_GIO_HARDWARE
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+
+using Banshee.Hardware;
+
+namespace Banshee.Hardware.Gio
+{
+    class BlockDevice : Device, IBlockDevice
+    {
+        // It's a block device if DEVTYPE is 'disk'
+        const string UdevDeviceType = "DEVTYPE";
+
+        public static new IBlockDevice Resolve (IDevice device)
+        {
+            var raw = device as IRawDevice;
+            if (device == null || raw.Device.UdevMetadata.GetPropertyString (UdevDeviceType) != "disk") {
+                return null;
+            }
+
+            RawBlockDevice rawBlock = null;
+            if (raw.Device is RawVolume) {
+                rawBlock = (raw.Device as RawVolume).Parent;
+            } else {
+                rawBlock = raw.Device as RawBlockDevice;
+            }
+
+            if (rawBlock == null) {
+                return null;
+            } else {
+                return (BlockDevice) CdromDevice.Resolve (device)
+                    ?? (BlockDevice) DiskDevice.Resolve (device);
+            }
+        }
+
+        public string DeviceNode {
+            get { return device.DeviceNode; }
+        }
+
+        public bool IsRemovable {
+            get { return device.IsRemovable; }
+        }
+
+        public IEnumerable<IVolume> Volumes {
+            get { return this; }
+        }
+
+        protected BlockDevice (RawDevice device)
+            : base (device)
+        {
+        }
+
+        IEnumerator IEnumerable.GetEnumerator ()
+        {
+            return GetEnumerator ();
+        }
+
+        public IEnumerator<IVolume> GetEnumerator ()
+        {
+            var rawBlock = (device is RawVolume)
+                ? (device as RawVolume).Parent
+                : device as RawBlockDevice;
+            if (rawBlock == null) {
+                yield break;
+            }
+
+            foreach (Volume volume in rawBlock.Volumes) {
+                yield return (IVolume) DiscVolume.Resolve (volume) ?? volume;
+            }
+        }
+    }
+}
+#endif
diff --git a/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/CdromDevice.cs b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/CdromDevice.cs
new file mode 100644
index 0000000..ea10ff8
--- /dev/null
+++ b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/CdromDevice.cs
@@ -0,0 +1,104 @@
+//
+// CdromDevice.cs
+//
+// Author:
+//   Alex Launi <alex launi gmail com>
+//
+// Copyright (c) 2010 Alex Launi
+//
+// 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.
+
+#if ENABLE_GIO_HARDWARE
+using System;
+using System.Runtime.InteropServices;
+using Mono.Unix;
+
+using Banshee.Hardware;
+
+namespace Banshee.Hardware.Gio
+{
+    class CdromDevice : BlockDevice, ICdromDevice
+    {
+        // This tells us the actual type of the block device
+        // i.e. 'disk' == HD. 'cd' == dvd/cd drive
+        const string DeviceType = "ID_TYPE";
+
+        public static new ICdromDevice Resolve (IDevice device)
+        {
+            var raw = device as IRawDevice;
+            if (raw != null) {
+                if (raw.Device.UdevMetadata.GetPropertyString (DeviceType) == "cd") {
+                    return new CdromDevice (raw.Device);
+                }
+            }
+
+            return null;
+        }
+
+        // FIXME: This is incredibly lame, there must be a way to query the
+        // device itself rather than hackisly attempting to keep track of it
+        public bool IsDoorLocked {
+            get; private set;
+        }
+
+        // This was literally copied and pasted from Hal's CdromDevice class.
+        [DllImport ("libc")]
+        private static extern int ioctl (int device, IoctlOperation request, bool lockdoor);
+
+        private enum IoctlOperation {
+            LockDoor = 0x5329
+        }
+
+        CdromDevice (RawDevice device)
+            : base (device)
+        {
+
+        }
+
+        bool LockDeviceNode (string device, bool lockdoor)
+        {
+            try {
+                using (UnixStream stream = (new UnixFileInfo (device)).Open (
+                    Mono.Unix.Native.OpenFlags.O_RDONLY |
+                    Mono.Unix.Native.OpenFlags.O_NONBLOCK)) {
+                    bool success = ioctl (stream.Handle, IoctlOperation.LockDoor, lockdoor) == 0;
+                    IsDoorLocked = success && lockdoor;
+                    return success;
+                }
+            } catch {
+                return false;
+            }
+        }
+
+        public bool LockDoor ()
+        {
+            lock (this) {
+                return LockDeviceNode (DeviceNode, true);
+            }
+        }
+
+        public bool UnlockDoor ()
+        {
+            lock (this) {
+                return LockDeviceNode (DeviceNode, false);
+            }
+        }
+    }
+}
+#endif
diff --git a/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/Device.cs b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/Device.cs
new file mode 100644
index 0000000..0095a20
--- /dev/null
+++ b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/Device.cs
@@ -0,0 +1,123 @@
+//
+// Device.cs
+//
+// Author:
+//   Alex Launi <alex launi gmail com>
+//
+// Copyright (c) 2010 Alex Launi
+//
+// 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.
+
+#if ENABLE_GIO_HARDWARE
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using GLib;
+using Banshee.Hardware;
+
+namespace Banshee.Hardware.Gio
+{
+    class Device : IDevice, IRawDevice
+    {
+        public static IDevice Resolve (IDevice device)
+        {
+            var raw = device as IRawDevice;
+            if (raw != null) {
+                return new Device (raw.Device);
+            }
+            return null;
+        }
+
+        protected RawDevice device;
+        RawDevice IRawDevice.Device {
+            get { return device; }
+        }
+
+        public IDeviceMediaCapabilities MediaCapabilities {
+            get { return device.MediaCapabilities; }
+        }
+
+        public string Name {
+            get { return device.Name; }
+        }
+
+        public string Serial {
+            get { return device.Serial; }
+        }
+
+        public string Product {
+            get { return device.Product; }
+        }
+
+        public string Uuid {
+            get { return device.Uuid; }
+        }
+
+        public string Vendor {
+            get { return device.Vendor; }
+        }
+
+        public Device (RawDevice device)
+        {
+            this.device = device;
+        }
+
+        public IUsbDevice ResolveRootUsbDevice ()
+        {
+            return null;
+        }
+
+        public bool PropertyExists (string key)
+        {
+            return device.PropertyExists (key);
+        }
+
+        public string GetPropertyString (string key)
+        {
+            return device.GetPropertyString (key);
+        }
+
+        public double GetPropertyDouble (string key)
+        {
+            return device.GetPropertyDouble (key);
+        }
+
+        public bool GetPropertyBoolean (string key)
+        {
+            return device.GetPropertyBoolean (key);
+        }
+
+        public int GetPropertyInteger (string key)
+        {
+            return device.GetPropertyInteger (key);
+        }
+
+        public ulong GetPropertyUInt64 (string key)
+        {
+            return device.GetPropertyUInt64 (key);
+        }
+
+        public string[] GetPropertyStringList (string key)
+        {
+            return device.GetPropertyStringList (key);
+        }
+    }
+}
+#endif
diff --git a/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/DeviceMediaCapabilities.cs b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/DeviceMediaCapabilities.cs
new file mode 100644
index 0000000..94e4235
--- /dev/null
+++ b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/DeviceMediaCapabilities.cs
@@ -0,0 +1,241 @@
+//
+// DeviceMediaCapabilities.cs
+//
+// Author:
+//   Alex Launi <alex launi gmail com>
+//
+// Copyright (c) 2010 Alex Launi
+//
+// 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.
+
+#if ENABLE_GIO_HARDWARE
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using KeyFile;
+
+using Banshee.Base;
+using Banshee.Hardware;
+using Banshee.IO;
+
+namespace Banshee.Hardware.Gio
+{
+    class DeviceMediaCapabilities : IDeviceMediaCapabilities
+    {
+        private GMpiFileInfo mpi;
+
+        // TODO implement. The technique for this will be to write a private
+        // MPI reader class that I can use to query the mpi file for `device'.
+        // the MPI file is found using the ID_MEDIA_PLAYER udev property + .mpi
+        // in /usr/[local/]share/.
+
+        public DeviceMediaCapabilities (RawDevice device)
+        {
+            mpi = new GMpiFileInfo (device.IdMediaPlayer);
+        }
+
+        public string[] OutputFormats {
+            get {
+                return mpi.OutputFormats;
+            }
+        }
+
+#region IDeviceMediaCapabilities implementation
+        public string[] AudioFolders {
+            get {
+                return mpi.AudioFolders;
+            }
+        }
+
+        // FIXME
+        // MPI has no property for this yet
+        public string CoverArtFileName {
+            get {
+                return "";
+            }
+        }
+
+        // FIXME
+        // MPI has no property for this yet
+        public string CoverArtFileType {
+            get {
+                return "";
+            }
+        }
+
+        // FIXME
+        // MPI has no property for this yet
+        public int CoverArtSize {
+            get {
+                return -1;
+            }
+        }
+
+
+        public int FolderDepth {
+            get {
+                return mpi.FolderDepth;
+            }
+        }
+
+
+        public bool IsType (string type)
+        {
+            return mpi.AccessProtocols.Contains (type);
+        }
+
+
+        public string[] PlaybackMimeTypes {
+            get {
+                return mpi.OutputFormats;
+            }
+        }
+
+
+        public string[] PlaylistFormats {
+            get {
+                return mpi.PlaylistFormats;
+            }
+        }
+
+
+        public string PlaylistPath {
+            get {
+                return mpi.PlaylistPath;
+            }
+        }
+
+        // FIXME
+        // MPI has no property for this yet
+        public string[] VideoFolders {
+            get {
+                return new string[] {""};
+            }
+        }
+#endregion
+        private class GMpiFileInfo
+        {
+            private const string Seperator = ";";
+            private const string MediaGroup = "Media";
+            private const string DeviceGroup = "Device";
+            private const string VendorGroup = "Vendor";
+            private const string StorageGroup = "storage";
+            private const string PlaylistGroup = "Playlist";
+
+            private GKeyFile mpi_file;
+
+            public GMpiFileInfo (string mediaPlayerId)
+            {
+                try {
+                    mpi_file = new GKeyFile ();
+                    mpi_file.ListSeparator = Seperator;
+                    mpi_file.LoadFromDirs (String.Format ("{0}.mpi", mediaPlayerId),
+                                           new string [] {"/usr/share/media-player-info",
+                                                          "/usr/local/share/media-player-info"},
+                                           null, Flags.None);
+                } catch (GLib.GException) {
+                }
+
+                LoadProperties ();
+            }
+
+            public string PlaylistPath {
+                get; private set;
+            }
+
+            public string[] AudioFolders {
+                get; private set;
+            }
+
+            public int FolderDepth {
+                get; private set;
+            }
+
+            public string[] AccessProtocols {
+                get; private set;
+            }
+
+            public string[] OutputFormats {
+                get; private set;
+            }
+
+            public string[] InputFormats {
+                get; private set;
+            }
+
+            public string[] PlaylistFormats {
+                get; private set;
+            }
+
+            private void LoadProperties ()
+            {
+                InitDefaults ();
+
+                if (mpi_file == null) {
+                    return;
+                }
+
+                if (mpi_file.HasGroup (StorageGroup)) {
+                    if (mpi_file.HasKey (StorageGroup, "FolderDepth")) {
+                        FolderDepth = mpi_file.GetInteger (StorageGroup, "FolderDepth");
+                    }
+
+                    if (mpi_file.HasKey (StorageGroup, "PlaylistPath")) {
+                        PlaylistPath = mpi_file.GetString (StorageGroup, "PlaylistPath");
+                    }
+
+                    if (mpi_file.HasKey (StorageGroup, "AudioFolders")) {
+                        AudioFolders = mpi_file.GetStringList (StorageGroup, "AudioFolders");
+                    }
+                }
+
+                if (mpi_file.HasGroup (MediaGroup)) {
+                    if (mpi_file.HasKey (MediaGroup, "InputFormats")) {
+                        InputFormats = mpi_file.GetStringList (MediaGroup, "InputFormats");
+                    }
+
+                    if (mpi_file.HasKey (MediaGroup, "OutputFormats")) {
+                        OutputFormats = mpi_file.GetStringList (MediaGroup, "OutputFormats");
+                    }
+                }
+
+                if (mpi_file.HasGroup (PlaylistGroup) && mpi_file.HasKey (PlaylistGroup, "Formats")) {
+                    PlaylistFormats = mpi_file.GetStringList (PlaylistGroup, "Formats") ?? new string [] {};
+                }
+
+                if (mpi_file.HasGroup (DeviceGroup) && mpi_file.HasKey (DeviceGroup, "AccessProtocols")) {
+                    AccessProtocols = mpi_file.GetStringList (DeviceGroup, "AccessProtocols") ?? new string [] {};
+                }
+            }
+
+            private void InitDefaults ()
+            {
+                FolderDepth = 0;
+                PlaylistPath = "";
+                AudioFolders = new string[] {};
+                InputFormats = new string[] {};
+                OutputFormats = new string[] {};
+                PlaylistFormats = new string[] {};
+                AccessProtocols = new string[] {};
+            }
+        }
+    }
+}
+#endif
diff --git a/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/DiscVolume.cs b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/DiscVolume.cs
new file mode 100644
index 0000000..96a2767
--- /dev/null
+++ b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/DiscVolume.cs
@@ -0,0 +1,83 @@
+//
+// DiskVolume.cs
+//
+// Author:
+//   Alex Launi <alex launi gmail com>
+//
+// Copyright (c) 2010 Alex Launi
+//
+// 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.
+
+#if ENABLE_GIO_HARDWARE
+using System;
+
+using Banshee.Hardware;
+
+namespace Banshee.Hardware.Gio
+{
+    class DiscVolume : Volume, IDiscVolume
+    {
+        public static new IDiscVolume Resolve (IDevice device)
+        {
+            var raw = device as IRawDevice;
+            if (raw != null && raw.Device is RawVolume) {
+                return new DiscVolume (raw.Device);
+            }
+
+            return null;
+        }
+
+        public bool HasAudio {
+            get {
+                return PropertyExists ("ID_CDROM_MEDIA_TRACK_COUNT_AUDIO");
+            }
+        }
+
+        public bool HasData {
+            get {
+                return PropertyExists ("ID_CDROM_MEDIA_TRACK_COUNT_DATA");
+            }
+        }
+
+        public bool IsBlank {
+            get {
+                return GetPropertyString ("ID_CDROM_MEDIA_STATE") == "blank";
+            }
+        }
+
+        public bool IsRewritable {
+            get {
+                return PropertyExists ("ID_CDROM_MEDIA_CD_RW");
+            }
+        }
+
+        public ulong MediaCapacity {
+            get {
+                return GetPropertyUInt64 ("size");
+            }
+        }
+
+        DiscVolume (RawDevice device)
+            : base (device)
+        {
+
+        }
+    }
+}
+#endif
diff --git a/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/DiskDevice.cs b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/DiskDevice.cs
new file mode 100644
index 0000000..7eab0a6
--- /dev/null
+++ b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/DiskDevice.cs
@@ -0,0 +1,58 @@
+//
+// DiskDevice.cs
+//
+// Author:
+//   Alex Launi <alex launi gmail com>
+//
+// Copyright (c) 2010 Alex Launi
+//
+// 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.
+
+#if ENABLE_GIO_HARDWARE
+using System;
+
+using Banshee.Hardware;
+using System.Collections.Generic;
+
+namespace Banshee.Hardware.Gio
+{
+    class DiskDevice : BlockDevice, IDiskDevice
+    {
+        // This tells us the actual type of the block device
+        // i.e. 'disk' == HD. 'cd' == dvd/cd drive
+        const string DeviceType = "ID_TYPE";
+
+        public static new IDiskDevice Resolve (IDevice device)
+        {
+            var raw = device as IRawDevice;
+            if (raw != null) {
+                if (raw.Device.UdevMetadata.GetPropertyString ("ID_TYPE") == "disk") {
+                    return new DiskDevice (raw.Device);
+                }
+            }
+            return null;
+        }
+
+        DiskDevice (RawDevice device)
+            : base (device)
+        {
+        }
+    }
+}
+#endif
diff --git a/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/HardwareManager.cs b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/HardwareManager.cs
new file mode 100644
index 0000000..26971b9
--- /dev/null
+++ b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/HardwareManager.cs
@@ -0,0 +1,126 @@
+//
+// HardwareManager.cs
+//
+// Author:
+//   Alex Launi <alex launi gmail com>
+//
+// Copyright (c) 2010 Alex Launi
+//
+// 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.
+
+#if ENABLE_GIO_HARDWARE
+using System;
+using System.Collections.Generic;
+
+using Banshee.Hardware;
+using Hyena;
+
+namespace Banshee.Hardware.Gio
+{
+    public class HardwareManager : IHardwareManager
+    {
+        private Manager manager;
+
+        public HardwareManager ()
+        {
+            manager = new Manager ();
+            manager.DeviceAdded += HandleManagerDeviceAdded;
+            manager.DeviceRemoved += HandleManagerDeviceRemoved;
+        }
+
+        public void Dispose ()
+        {
+            manager.Dispose ();
+        }
+
+        void HandleManagerDeviceAdded (object o, MountArgs args)
+        {
+            HandleManagerDeviceAdded (args.Device);
+        }
+
+        void HandleManagerDeviceRemoved (object o, MountArgs args)
+        {
+            if (DeviceRemoved != null) {
+                DeviceRemoved (this, new DeviceRemovedArgs (args.Device.Uuid));
+            }
+        }
+
+        void HandleManagerDeviceAdded (IDevice device)
+        {
+            if (device != null && DeviceAdded != null) {
+                DeviceAdded (this, new DeviceAddedArgs (device));
+            }
+        }
+
+#region IHardwareManager
+        public event DeviceAddedHandler DeviceAdded;
+        public event DeviceRemovedHandler DeviceRemoved;
+
+        public IEnumerable<IDevice> GetAllDevices ()
+        {
+            foreach (IDevice device in manager.GetAllDevices ()) {
+                if (device != null) {
+                    yield return device;
+                }
+            }
+        }
+
+        public IEnumerable<IBlockDevice> GetAllBlockDevices ()
+        {
+            return GetAllBlockDevices<IBlockDevice> ();
+        }
+
+        public IEnumerable<ICdromDevice> GetAllCdromDevices ()
+        {
+            return GetAllBlockDevices<ICdromDevice> ();
+        }
+
+        public IEnumerable<IDiskDevice> GetAllDiskDevices ()
+        {
+            return GetAllBlockDevices<IDiskDevice> ();
+        }
+#endregion
+
+        private IEnumerable<T> GetAllBlockDevices<T> () where T : IBlockDevice
+        {
+            foreach (var lowDevice in manager.GetAllDevices ()) {
+                IBlockDevice device = lowDevice as IBlockDevice;
+                if (device != null) {
+                    yield return (T) device;
+                }
+            }
+        }
+
+        internal static IDevice Resolve (IDevice device)
+        {
+            IDevice dev = BlockDevice.Resolve (device);
+            if (dev == null)
+                dev = UsbVolume.Resolve (device);
+            if (dev == null)
+                dev = Volume.Resolve (device);
+            if (dev == null)
+                dev = UsbDevice.Resolve (device);
+            if (dev == null)
+                dev = Device.Resolve (device);
+
+            return dev;
+        }
+    }
+}
+#endif
diff --git a/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/LowLevel/GioDriveMetadetaSource.cs b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/LowLevel/GioDriveMetadetaSource.cs
new file mode 100644
index 0000000..97df8e5
--- /dev/null
+++ b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/LowLevel/GioDriveMetadetaSource.cs
@@ -0,0 +1,81 @@
+//
+// GioDriveMetadetaSource.cs
+//
+// Author:
+//   alex <${AuthorEmail}>
+//
+// Copyright (c) 2010 alex
+//
+// 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.
+
+#if ENABLE_GIO_HARDWARE
+using System;
+
+using GLib;
+
+namespace Banshee.Hardware.Gio
+{
+    public class GioDriveMetadetaSource : GioMetadataSource
+    {
+        Drive Drive { get; set; }
+
+        public GioDriveMetadetaSource (Drive drive)
+        {
+            Drive = drive;
+        }
+
+#region implemented abstract members of Banshee.Hardware.Gio.GioMetadataSource
+        public override string GetPropertyString (string key)
+        {
+            throw new System.NotImplementedException();
+        }
+
+        public override double GetPropertyDouble (string key)
+        {
+            throw new System.NotImplementedException();
+        }
+
+        public override bool GetPropertyBoolean (string key)
+        {
+            throw new System.NotImplementedException();
+        }
+
+        public override int GetPropertyInteger (string key)
+        {
+            throw new System.NotImplementedException();
+        }
+
+        public override ulong GetPropertyUInt64 (string key)
+        {
+            throw new System.NotImplementedException();
+        }
+
+        public override string[] GetPropertyStringList (string key)
+        {
+            throw new System.NotImplementedException();
+        }
+
+        public override bool PropertyExists (string key)
+        {
+            throw new System.NotImplementedException();
+        }
+#endregion
+    }
+}
+#endif
diff --git a/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/LowLevel/GioMetadataSource.cs b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/LowLevel/GioMetadataSource.cs
new file mode 100644
index 0000000..467d052
--- /dev/null
+++ b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/LowLevel/GioMetadataSource.cs
@@ -0,0 +1,52 @@
+//
+// GioMetadataSource.cs
+//
+// Author:
+//   alex <${AuthorEmail}>
+//
+// Copyright (c) 2010 alex
+//
+// 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.
+
+#if ENABLE_GIO_HARDWARE
+using System;
+
+namespace Banshee.Hardware.Gio
+{
+    public abstract class GioMetadataSource : IMetadataSource
+    {
+#region IMetadataSource implementation
+        public abstract string GetPropertyString (string key);
+
+        public abstract double GetPropertyDouble (string key);
+
+        public abstract bool GetPropertyBoolean (string key);
+
+        public abstract int GetPropertyInteger (string key);
+
+        public abstract ulong GetPropertyUInt64 (string key);
+
+        public abstract string[] GetPropertyStringList (string key);
+
+        public abstract bool PropertyExists (string key);
+    }
+#endregion
+}
+
+#endif
diff --git a/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/LowLevel/GioVolumeMetadataSource.cs b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/LowLevel/GioVolumeMetadataSource.cs
new file mode 100644
index 0000000..9a861fc
--- /dev/null
+++ b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/LowLevel/GioVolumeMetadataSource.cs
@@ -0,0 +1,80 @@
+//
+// GioVolumeMetadataSource.cs
+//
+// Author:
+//   Alan McGovern <amcgovern novell com>
+//
+// Copyright (c) 2010 Moonlight Team
+//
+// 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.
+
+#if ENABLE_GIO_HARDWARE
+using System;
+
+namespace Banshee.Hardware.Gio
+{
+    public class GioVolumeMetadataSource : GioMetadataSource
+    {
+        GLib.Volume Volume {
+            get; set;
+        }
+
+        public GioVolumeMetadataSource (GLib.Volume volume)
+        {
+            Volume = volume;
+        }
+
+        public override string GetPropertyString (string key)
+        {
+            throw new NotImplementedException ();
+        }
+
+        public override double GetPropertyDouble (string key)
+        {
+            throw new NotImplementedException ();
+        }
+
+        public override bool GetPropertyBoolean (string key)
+        {
+            throw new NotImplementedException ();
+        }
+
+        public override int GetPropertyInteger (string key)
+        {
+            throw new NotImplementedException ();
+        }
+
+        public override ulong GetPropertyUInt64 (string key)
+        {
+            throw new NotImplementedException ();
+        }
+
+        public override string[] GetPropertyStringList (string key)
+        {
+            throw new NotImplementedException ();
+        }
+
+        public override bool PropertyExists (string key)
+        {
+            throw new NotImplementedException ();
+        }
+    }
+}
+
+#endif
diff --git a/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/LowLevel/IMetadataSource.cs b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/LowLevel/IMetadataSource.cs
new file mode 100644
index 0000000..93298c7
--- /dev/null
+++ b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/LowLevel/IMetadataSource.cs
@@ -0,0 +1,42 @@
+//
+// IMetadataSource.cs
+//
+// Author:
+//   Alan McGovern <amcgovern novell com>
+//
+// Copyright (c) 2010 Moonlight Team
+//
+// 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.
+#if ENABLE_GIO_HARDWARE
+using System;
+namespace Banshee.Hardware.Gio
+{
+    public interface IMetadataSource
+    {
+        string GetPropertyString (string key);
+        double GetPropertyDouble (string key);
+        bool GetPropertyBoolean (string key);
+        int GetPropertyInteger (string key);
+        ulong GetPropertyUInt64 (string key);
+        string[] GetPropertyStringList (string key);
+        bool PropertyExists (string key);
+    }
+}
+
+#endif
diff --git a/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/LowLevel/IRawDevice.cs b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/LowLevel/IRawDevice.cs
new file mode 100644
index 0000000..300b187
--- /dev/null
+++ b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/LowLevel/IRawDevice.cs
@@ -0,0 +1,38 @@
+//
+// IRawDevice.cs
+//
+// Author:
+//   Alan McGovern <amcgovern novell com>
+//
+// Copyright (c) 2010 Moonlight Team
+//
+// 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.
+
+#if ENABLE_GIO_HARDWARE
+using System;
+
+namespace Banshee.Hardware.Gio
+{
+    interface IRawDevice
+    {
+        RawDevice Device { get; }
+    }
+}
+
+#endif
diff --git a/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/LowLevel/Manager.cs b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/LowLevel/Manager.cs
new file mode 100644
index 0000000..a5a6fab
--- /dev/null
+++ b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/LowLevel/Manager.cs
@@ -0,0 +1,240 @@
+//
+// Manager.cs
+//
+// Author:
+//   Alex Launi <alex launi gmail com>
+//
+// Copyright (c) 2010 Alex Launi
+//
+// 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.
+
+#if ENABLE_GIO_HARDWARE
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+
+using GLib;
+using GUdev;
+using System.Runtime.InteropServices;
+using Banshee.Hardware;
+
+namespace Banshee.Hardware.Gio
+{
+    public class Manager : IEnumerable<IDevice>, IDisposable
+    {
+        private readonly string[] subsystems = new string[] {"block", "usb"};
+
+        private Client client;
+        private VolumeMonitor monitor;
+
+        public event EventHandler<MountArgs> DeviceAdded;
+        public event EventHandler<MountArgs> DeviceRemoved;
+
+        public Manager ()
+        {
+            client = new Client (subsystems);
+            monitor = VolumeMonitor.Default;
+            monitor.MountAdded += HandleMonitorMountAdded;
+            monitor.MountRemoved += HandleMonitorMountRemoved;
+        }
+//
+//        void HandleClientUevent (object o, UeventArgs args)
+//        {
+//            if (args.Action == "add")
+//                TryAddUdevDevice (args.Device);
+//            else if (args.Action == "remove")
+//                TryRemoveUdevDevice (args.Device);
+//            else
+//                Console.WriteLine ("Unknown action: {0}", args.Action);
+//        }
+//
+//        void TryAddUdevDevice (GUdev.Device device)
+//        {
+//            // We only want to match MTP devices for the moment. GIO should be able
+//            // to discover everything else.
+//            if (device.GetPropertyAsInt ("ID_GPHOTO2") == 1 &&
+//                device.GetPropertyAsInt ("ID_MEDIA_PLAYER") == 1) {
+//                var h = DeviceAdded;
+//                if (h != null) {
+//                    var v = new UsbDevice (new UDevDevice (this,
+//                                              null,
+//                                              new UdevMetadataSource (device)));
+//                    h (this, new MountArgs (v));
+//                }
+//            }
+//        }
+//
+//        void TryRemoveUdevDevice (GUdev.Device device)
+//        {
+//            if (device.GetPropertyAsInt ("ID_GPHOTO2") == 1 &&
+//                device.GetPropertyAsInt ("ID_MEDIA_PLAYER") == 1) {
+//
+//            }
+//        }
+//
+
+#region IDisposable
+        public void Dispose ()
+        {
+            client.Dispose ();
+            monitor.Dispose ();
+        }
+#endregion
+
+        void HandleMonitorMountAdded (object o, MountAddedArgs args)
+        {
+            // Manually get the mount as gio-sharp translates it to the wrong managed object
+            var mount = GLib.MountAdapter.GetObject ((GLib.Object) args.Args [0]);
+            if (mount.Volume == null)
+                return;
+
+            var device = GudevDeviceFromGioMount (mount);
+            var h = DeviceAdded;
+            if (h != null) {
+                var v = new RawVolume (mount.Volume,
+                                          this,
+                                          new GioVolumeMetadataSource (mount.Volume),
+                                          new UdevMetadataSource (device));
+                h (this, new MountArgs (HardwareManager.Resolve (new Device (v))));
+            }
+        }
+
+        void HandleMonitorMountRemoved (object o, MountRemovedArgs args)
+        {
+            // Manually get the mount as gio-sharp translates it to the wrong managed object
+            var mount = GLib.MountAdapter.GetObject ((GLib.Object) args.Args [0]);
+            if (mount.Volume == null || mount.Root.Path == null)
+                return;
+
+            var h = DeviceRemoved;
+            if (h != null) {
+                var v = new RawVolume (mount.Volume,
+                                          this,
+                                          new GioVolumeMetadataSource (mount.Volume),
+                                          new UdevMetadataSource (null));
+                h (this, new MountArgs (new Device (v)));
+            }
+        }
+
+        public IEnumerable<IDevice> GetAllDevices ()
+        {
+            foreach (GLib.Volume vol in monitor.Volumes) {
+                var device = GudevDeviceFromGioVolume (vol);
+                if (device == null) {
+                    continue;
+                }
+
+                var raw = new RawVolume (vol,
+                                         this,
+                                         new GioVolumeMetadataSource (vol),
+                                         new UdevMetadataSource (device));
+                yield return HardwareManager.Resolve (new Device (raw));
+            }
+        }
+
+        public GUdev.Device GudevDeviceFromSubsystemPropertyValue (string sub, string prop, string val)
+        {
+            foreach (GUdev.Device dev in client.QueryBySubsystem (sub)) {
+                if (dev.HasProperty (prop) && dev.GetProperty (prop) == val)
+                    return dev;
+            }
+
+            return null;
+        }
+
+
+        public GUdev.Device GudevDeviceFromGioDrive (GLib.Drive drive)
+        {
+            GUdev.Device device = null;
+
+            if (drive == null) {
+                return null;
+            }
+
+            string devFile = drive.GetIdentifier ("unix-device");
+            if (!String.IsNullOrEmpty (devFile)) {
+                device = client.QueryByDeviceFile (devFile);
+            }
+
+            return device;
+        }
+
+        public GUdev.Device GudevDeviceFromGioVolume (GLib.Volume volume)
+        {
+            GUdev.Device device = null;
+
+            if (volume == null) {
+                return null;
+            }
+
+            var s = volume.GetIdentifier ("unix-device");
+            if (!String.IsNullOrEmpty (s)) {
+                device = client.QueryByDeviceFile (s);
+            }
+
+            if (device == null) {
+                s = volume.Uuid;
+                foreach (GUdev.Device d in client.QueryBySubsystem ("usb")) {
+                    if (s == d.GetSysfsAttr ("serial")) {
+                        device = d;
+                        break;
+                    }
+                }
+            }
+
+            return device;
+        }
+
+        public GUdev.Device GudevDeviceFromGioMount (GLib.Mount mount)
+        {
+            if (mount == null) {
+                return null;
+            }
+
+            return GudevDeviceFromGioVolume (mount.Volume);
+        }
+
+#region IEnumerable
+        public IEnumerator<IDevice> GetEnumerator ()
+        {
+            foreach (var device in GetAllDevices ())
+                yield return device;
+        }
+
+        IEnumerator IEnumerable.GetEnumerator ()
+        {
+            return GetEnumerator ();
+        }
+#endregion
+    }
+
+    public class MountArgs : EventArgs
+    {
+        public IDevice Device {
+            get; private set;
+        }
+
+        public MountArgs (IDevice device)
+        {
+            Device = device;
+        }
+    }
+}
+#endif
diff --git a/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/LowLevel/RawBlockDevice.cs b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/LowLevel/RawBlockDevice.cs
new file mode 100644
index 0000000..765b86e
--- /dev/null
+++ b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/LowLevel/RawBlockDevice.cs
@@ -0,0 +1,164 @@
+//
+// RawBlockDevice.cs
+//
+// Author:
+//   alex <${AuthorEmail}>
+//
+// Copyright (c) 2010 alex
+//
+// 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.
+#if ENABLE_GIO_HARDWARE
+using System;
+using System.Collections.Generic;
+
+using Banshee.Hardware;
+
+namespace Banshee.Hardware.Gio
+{
+    class RawBlockDevice : RawDevice
+    {
+        public RawBlockDevice (GLib.Drive drive, Manager manager, GioDriveMetadetaSource gioMetadata, UdevMetadataSource udevMetadata)
+            : base (manager, gioMetadata, udevMetadata)
+        {
+            Drive = drive;
+        }
+
+        GLib.Drive Drive { get; set; }
+
+        public IEnumerable<Volume> Volumes {
+            get {
+                foreach (var notVolume in Drive.Volumes) {
+                    var volume = GLib.VolumeAdapter.GetObject (notVolume as GLib.Object);
+                    if (volume == null) {
+                        yield return null;
+                    }
+                    yield return new Volume (new RawVolume (volume,
+                                                            Manager,
+                                                            new GioVolumeMetadataSource (volume),
+                                                            new UdevMetadataSource (Manager.GudevDeviceFromGioVolume (volume))));
+                }
+            }
+        }
+
+#region implemented abstract members of Banshee.Hardware.Gio.RawDevice
+        public override string Identifier {
+           get {
+               return Uuid;
+           }
+        }
+
+        public override string IdMediaPlayer {
+           get {
+               return UdevMetadata.IdMediaDevice;
+           }
+        }
+
+        public override bool IsRemovable {
+           get {
+               return Drive.CanEject ();
+           }
+        }
+
+        public override IDeviceMediaCapabilities MediaCapabilities {
+           get {
+               return new DeviceMediaCapabilities (this);
+           }
+        }
+
+        public override string Name {
+           get {
+               return Drive.Name;
+           }
+        }
+
+        public override string Model {
+           get {
+               return UdevMetadata.Model;
+           }
+        }
+
+        public override string Product {
+           get {
+               return "Product not implemented";
+           }
+        }
+
+        public override string Serial {
+           get {
+               return UdevMetadata.Serial;
+           }
+        }
+
+        public override string Subsystem {
+           get {
+               return UdevMetadata.Subsystem;
+           }
+        }
+
+        public override string Uuid {
+           get {
+               return UdevMetadata.Uuid;
+           }
+        }
+
+        public override string Vendor {
+           get {
+               return UdevMetadata.Vendor;
+           }
+        }
+
+        public override string GetPropertyString (string key)
+        {
+           return UdevMetadata.GetPropertyString (key);
+        }
+
+        public override double GetPropertyDouble (string key)
+        {
+           return UdevMetadata.GetPropertyDouble (key);
+        }
+
+        public override bool GetPropertyBoolean (string key)
+        {
+           return UdevMetadata.GetPropertyBoolean (key);
+        }
+
+        public override int GetPropertyInteger (string key)
+        {
+           return UdevMetadata.GetPropertyInteger (key);
+        }
+
+        public override ulong GetPropertyUInt64 (string key)
+        {
+           return UdevMetadata.GetPropertyUInt64 (key);
+        }
+
+        public override string[] GetPropertyStringList (string key)
+        {
+           return UdevMetadata.GetPropertyStringList (key);
+        }
+
+        public override bool PropertyExists (string key)
+        {
+           return UdevMetadata.PropertyExists (key);
+        }
+#endregion
+    }
+}
+
+#endif
diff --git a/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/LowLevel/RawDevice.cs b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/LowLevel/RawDevice.cs
new file mode 100644
index 0000000..b9a0ccd
--- /dev/null
+++ b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/LowLevel/RawDevice.cs
@@ -0,0 +1,146 @@
+//
+// Device.cs
+//
+// Author:
+//   Alex Launi <alex launi gmail com>
+//
+// Copyright (c) 2010 Alex Launi
+//
+// 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.
+
+#if ENABLE_GIO_HARDWARE
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using GLib;
+using Banshee.Hardware;
+
+namespace Banshee.Hardware.Gio
+{
+    /// <summary>
+    /// A Device is a wrapper around the two metadata source, udev and gio. Banshee needs information
+    /// from both sources, so this Device class is meant to provide a level of abstraction.
+    /// </summary>
+    abstract class RawDevice : IEquatable<RawDevice>, IComparable<RawDevice>, IRawDevice
+    {
+        const string UdevDevicePath = "DEVNAME";
+
+        RawDevice IRawDevice.Device {
+            get { return this; }
+        }
+
+        public string DeviceNode {
+            get { return UdevMetadata.GetPropertyString (UdevDevicePath); }
+        }
+
+        internal GioMetadataSource GioMetadata {
+            get; private set;
+        }
+
+        internal UdevMetadataSource UdevMetadata {
+            get; private set;
+        }
+
+        public abstract string Identifier {
+            get;
+        }
+
+        public abstract string IdMediaPlayer {
+            get;
+        }
+
+        public abstract bool IsRemovable {
+            get;
+        }
+
+        public abstract IDeviceMediaCapabilities MediaCapabilities {
+            get;
+        }
+
+        public abstract string Name {
+            get;
+        }
+
+        public Manager Manager {
+            get; private set;
+        }
+
+        public abstract string Model {
+            get;
+        }
+
+        public abstract string Product {
+            get;
+        }
+
+        public abstract string Serial {
+            get;
+        }
+
+        public abstract string Subsystem {
+            get;
+        }
+
+        public abstract string Uuid {
+            get;
+        }
+
+        public abstract string Vendor {
+            get;
+        }
+
+        protected RawDevice (Manager manager, GioMetadataSource gioMetadata, UdevMetadataSource udevMetadata)
+        {
+            Manager = manager;
+            GioMetadata = gioMetadata;
+            UdevMetadata = udevMetadata;
+        }
+
+        public bool Equals (RawDevice other)
+        {
+            return Identifier == other.Identifier;
+        }
+
+        public int CompareTo (RawDevice other)
+        {
+            return string.Compare (Identifier, other.Identifier);
+        }
+
+        public override int GetHashCode ()
+        {
+            return Identifier.GetHashCode ();
+        }
+
+        public abstract string GetPropertyString (string key);
+
+        public abstract double GetPropertyDouble (string key);
+
+        public abstract bool GetPropertyBoolean (string key);
+
+        public abstract int GetPropertyInteger (string key);
+
+        public abstract ulong GetPropertyUInt64 (string key);
+
+        public abstract string[] GetPropertyStringList (string key);
+
+        public abstract bool PropertyExists (string key);
+    }
+}
+#endif
diff --git a/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/LowLevel/RawVolume.cs b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/LowLevel/RawVolume.cs
new file mode 100644
index 0000000..a2e276d
--- /dev/null
+++ b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/LowLevel/RawVolume.cs
@@ -0,0 +1,254 @@
+//
+// Volume.cs
+//
+// Author:
+//   Alex Launi <alex launi gmail com>
+//
+// Copyright (c) 2010 Alex Launi
+//
+// 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.
+
+#if ENABLE_GIO_HARDWARE
+using System;
+using System.Collections.Generic;
+
+using Mono.Unix;
+
+using Banshee.Hardware;
+using GLib;
+using System.Threading;
+
+namespace Banshee.Hardware.Gio
+{
+    class RawVolume : RawDevice
+    {
+        const string FileSystemFree = "filesystem::free";
+        const string FileSystemSize = "filesystem::size";
+        const string FileSystemReadOnly = "filesystem::readonly";
+
+        public GLib.Volume Volume {
+            get; set;
+        }
+
+        public long Available {
+            get {
+                try {
+                    using (var file_info = Volume.MountInstance.Root.QueryFilesystemInfo (FileSystemFree, null))
+                        return (long) file_info.GetAttributeULong (FileSystemFree);
+                } catch {
+                    return 0;
+                }
+            }
+        }
+
+        public ulong Capacity {
+            get {
+                try {
+                    using (var file_info = Volume.MountInstance.Root.QueryFilesystemInfo (FileSystemSize, null))
+                        return file_info.GetAttributeULong (FileSystemSize);
+                } catch {
+                    return 0;
+                }
+            }
+        }
+
+        public bool CanEject{
+            get { return Volume.CanEject (); }
+        }
+
+        public bool CanMount {
+            get {
+                return Volume.CanMount ();
+            }
+        }
+
+        public bool CanUnmount {
+            get {
+                return IsMounted && Volume.MountInstance.CanUnmount;
+            }
+        }
+
+        public override string IdMediaPlayer {
+            get { return UdevMetadata.IdMediaDevice; }
+        }
+
+        public bool IsMounted {
+            get {
+                return Volume.MountInstance != null;
+            }
+        }
+
+        public bool IsReadOnly {
+            get {
+                try {
+                    using (var file_info = Volume.MountInstance.Root.QueryFilesystemInfo (FileSystemReadOnly, null))
+                        return file_info.GetAttributeBoolean (FileSystemReadOnly);
+                } catch {
+                    return true;
+                }
+            }
+        }
+
+        public override bool IsRemovable {
+            get {
+                return Volume.CanEject ();
+            }
+        }
+
+        // FIXME: iPhones have an empty UUID so we should return their serial instead.
+        public override string Identifier {
+            get { return Uuid; }
+        }
+
+        // FIXME
+        public override string Model {
+            get { return UdevMetadata.Model; }
+        }
+
+        public string MountPoint {
+            get {
+                return Volume.MountInstance.Root.Path;
+            }
+        }
+
+        public override string Name {
+            get { return Volume.Name; }
+        }
+
+        // FIXME
+        public override string Serial {
+            get { return UdevMetadata.Serial; }
+        }
+
+        // FIXME
+        public override string Subsystem {
+            get { return UdevMetadata.Subsystem; }
+        }
+
+        //FIXME
+        public override string Vendor {
+            get { return UdevMetadata.Vendor; }
+        }
+
+
+        public RawVolume (GLib.Volume volume, Manager manager, GioVolumeMetadataSource gioMetadata, UdevMetadataSource udevMetadata)
+            : base (manager, gioMetadata, udevMetadata)
+        {
+            Volume = volume;
+        }
+
+        public void Eject ()
+        {
+            if (CanEject) {
+                Volume.Eject (MountUnmountFlags.Force, null, (s, result) =>
+                {
+                    try {
+                        if (!Volume.EjectWithOperationFinish (result))
+                            Hyena.Log.ErrorFormat ("Failed to eject {0}", Volume.Name);
+                    } catch (Exception e) {
+                        Hyena.Log.Exception (e);
+                    }
+                });
+            }
+        }
+
+        public override string GetPropertyString (string key)
+        {
+            return UdevMetadata.GetPropertyString (key);
+        }
+
+        public override double GetPropertyDouble (string key)
+        {
+            return UdevMetadata.GetPropertyDouble (key);
+        }
+
+        public override bool GetPropertyBoolean (string key)
+        {
+            return UdevMetadata.GetPropertyBoolean (key);
+        }
+
+        public override int GetPropertyInteger (string key)
+        {
+            return UdevMetadata.GetPropertyInteger (key);
+        }
+
+        public override ulong GetPropertyUInt64 (string key)
+        {
+            return UdevMetadata.GetPropertyUInt64 (key);
+        }
+
+        public override string[] GetPropertyStringList (string key)
+        {
+            return UdevMetadata.GetPropertyStringList (key);
+        }
+
+        public override bool PropertyExists (string key)
+        {
+            return UdevMetadata.PropertyExists (key);
+        }
+
+        public void Mount ()
+        {
+            if (CanMount)
+                Volume.Mount (MountMountFlags.None, null, null, null);
+        }
+
+        public void Unmount ()
+        {
+            if (CanUnmount) {
+                ManualResetEvent handle = new ManualResetEvent (false);
+                Volume.MountInstance.UnmountWithOperation (MountUnmountFlags.Force, null, null, delegate { handle.Set (); });
+                handle.WaitOne (TimeSpan.FromSeconds (5));
+            }
+        }
+
+        public override IDeviceMediaCapabilities MediaCapabilities {
+            get { return new DeviceMediaCapabilities (this); }
+        }
+
+        public override string Product {
+            get { return "Product Not Implemented"; }
+        }
+
+        public override string Uuid {
+            get { return UdevMetadata.Uuid; }
+        }
+
+        public RawBlockDevice Parent {
+            get {
+                if (Volume.Drive == null) {
+                    return null;
+                }
+                return new RawBlockDevice (Volume.Drive,
+                                           Manager,
+                                           new GioDriveMetadetaSource (Volume.Drive),
+                                           new UdevMetadataSource (Manager.GudevDeviceFromGioDrive (Volume.Drive)));
+            }
+        }
+
+        public bool ShouldIgnore {
+            get { return false; }
+        }
+
+        public string FileSystem {
+            get { return Volume.MountInstance.Root.UriScheme; }
+        }
+    }
+}
+#endif
diff --git a/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/LowLevel/UdevMetadataSource.cs b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/LowLevel/UdevMetadataSource.cs
new file mode 100644
index 0000000..2cc597f
--- /dev/null
+++ b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/LowLevel/UdevMetadataSource.cs
@@ -0,0 +1,110 @@
+//
+// UdevMetadataSource.cs
+//
+// Author:
+//   Alan McGovern <amcgovern novell com>
+//
+// Copyright (c) 2010 Moonlight Team
+//
+// 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.
+#if ENABLE_GIO_HARDWARE
+using System;
+namespace Banshee.Hardware.Gio
+{
+    public class UdevMetadataSource : IMetadataSource
+    {
+        GUdev.Device Device {
+            get; set;
+        }
+
+        public string IdMediaDevice {
+            get { return Device.GetProperty ("ID_MEDIA_PLAYER"); }
+        }
+
+        public string Model {
+            get { return Device.GetProperty ("ID_MODEL"); }
+        }
+
+        public string Name {
+            get { return Device.Name; }
+        }
+
+        public string Product {
+            get { return Device.GetProperty ("PRODUCT"); }
+        }
+
+        public string Serial {
+            get { return GetPropertyString ("ID_SERIAL_SHORT"); }
+        }
+
+        public string Uuid {
+            get { return GetPropertyString ("DEVPATH"); }
+        }
+
+        public string Vendor {
+            get { return GetPropertyString ("ID_VENDOR"); }
+        }
+
+        public string Subsystem {
+            get { return GetPropertyString ("SUBSYSTEM"); }
+        }
+
+        public UdevMetadataSource (GUdev.Device device)
+        {
+            Device = device;
+        }
+
+        public string GetPropertyString (string key)
+        {
+            return Device.GetProperty (key);
+        }
+
+        public double GetPropertyDouble (string key)
+        {
+            return Device.GetPropertyAsDouble (key);
+        }
+
+        public bool GetPropertyBoolean (string key)
+        {
+            return Device.GetPropertyAsBoolean (key);
+        }
+
+        public int GetPropertyInteger (string key)
+        {
+            return Device.GetPropertyAsInt (key);
+        }
+
+        public ulong GetPropertyUInt64 (string key)
+        {
+            return Device.GetPropertyAsUint64 (key);
+        }
+
+        public string[] GetPropertyStringList (string key)
+        {
+            return Device.GetPropertyAsStrv (key);
+        }
+
+        public bool PropertyExists (string key)
+        {
+            return Device.HasProperty (key);
+        }
+    }
+}
+
+#endif
diff --git a/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/UsbDevice.cs b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/UsbDevice.cs
new file mode 100644
index 0000000..bcbc7af
--- /dev/null
+++ b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/UsbDevice.cs
@@ -0,0 +1,189 @@
+//
+// UsbDevice.cs
+//
+// Author:
+//   Alex Launi <alex launi gmail com>
+//
+// Copyright (c) 2010 Alex Launi
+//
+// 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.
+
+#if ENABLE_GIO_HARDWARE
+using System;
+
+using Banshee.Hardware;
+
+using GUdev;
+using System.Globalization;
+
+namespace Banshee.Hardware.Gio
+{
+    class UsbDevice : IUsbDevice, IRawDevice
+    {
+        const string UdevUsbBusNumber = "BUSNUM";
+        const string UdevUsbDeviceNumber = "DEVNUM";
+        const string UdevVendorId = "ID_VENDOR_ID";
+        const string UdevProductId = "ID_MODEL_ID";
+
+        public IUsbDevice ResolveRootUsbDevice ()
+        {
+            return null;
+        }
+
+        public static int GetBusNumber (IUsbDevice device)
+        {
+            var raw = device as IRawDevice;
+            return raw == null ? 0 : int.Parse (raw.Device.UdevMetadata.GetPropertyString (UdevUsbBusNumber));
+        }
+
+        public static int GetDeviceNumber (IUsbDevice device)
+        {
+            var raw = device as IRawDevice;
+            return raw ==  null ? 0 : int.Parse (raw.Device.UdevMetadata.GetPropertyString (UdevUsbDeviceNumber));
+        }
+
+        public static int GetProductId (IUsbDevice device)
+        {
+            var raw = device as IRawDevice;
+            return raw == null ? 0 : int.Parse (raw.Device.UdevMetadata.GetPropertyString (UdevProductId), NumberStyles.HexNumber);
+        }
+
+        public static int GetSpeed (IUsbDevice device)
+        {
+            throw new NotImplementedException ();
+        }
+
+        public static int GetVendorId (IUsbDevice device)
+        {
+            var raw = device as IRawDevice;
+            return raw == null ? 0 : int.Parse (raw.Device.UdevMetadata.GetPropertyString (UdevVendorId), NumberStyles.HexNumber);
+        }
+
+        public static int GetVersion (IUsbDevice device)
+        {
+            throw new NotImplementedException ();
+        }
+
+        public static IUsbDevice Resolve (IDevice device)
+        {
+            IRawDevice raw = device as IRawDevice;
+            if (raw != null) {
+                var metadata = raw.Device.UdevMetadata;
+                if (metadata.PropertyExists (UdevUsbBusNumber) && metadata.PropertyExists (UdevUsbDeviceNumber))
+                    return new UsbDevice (raw.Device);
+            }
+            return null;
+        }
+
+        public RawDevice Device {
+            get; set;
+        }
+
+        public int BusNumber {
+            get { return GetBusNumber (this); }
+        }
+
+        public int DeviceNumber {
+            get { return GetDeviceNumber (this); }
+        }
+
+        public string Name {
+            get { return Device.Name; }
+        }
+
+        public IDeviceMediaCapabilities MediaCapabilities {
+            get { return Device.MediaCapabilities; }
+        }
+
+        public string Product {
+            get { return Device.Product;}
+        }
+
+        public int ProductId {
+            get { return GetProductId (this); }
+        }
+
+        public string Serial {
+            get { return Device.Serial; }
+        }
+
+        // What is this and why do we want it?
+        public double Speed {
+            get { return GetSpeed (this); }
+        }
+
+        public string Uuid {
+            get { return Device.Uuid; }
+        }
+
+        public string Vendor {
+            get { return Device.Vendor; }
+        }
+
+        public int VendorId {
+            get { return GetVendorId (this); }
+        }
+
+        // What is this and why do we want it?
+        public double Version {
+            get { return GetVersion (this); }
+        }
+
+        UsbDevice (RawDevice device)
+        {
+            Device = device;
+        }
+
+        bool IDevice.PropertyExists (string key)
+        {
+            return Device.PropertyExists (key);
+        }
+
+        string IDevice.GetPropertyString (string key)
+        {
+            return Device.GetPropertyString (key);
+        }
+
+        double IDevice.GetPropertyDouble (string key)
+        {
+            return Device.GetPropertyDouble (key);
+        }
+
+        bool IDevice.GetPropertyBoolean (string key)
+        {
+            return Device.GetPropertyBoolean (key);
+        }
+
+        int IDevice.GetPropertyInteger (string key)
+        {
+            return Device.GetPropertyInteger (key);
+        }
+
+        ulong IDevice.GetPropertyUInt64 (string key)
+        {
+            return Device.GetPropertyUInt64 (key);
+        }
+
+        public string[] GetPropertyStringList (string key)
+        {
+            return Device.GetPropertyStringList (key);
+        }
+    }
+}
+#endif
diff --git a/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/UsbVolume.cs b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/UsbVolume.cs
new file mode 100644
index 0000000..1739626
--- /dev/null
+++ b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/UsbVolume.cs
@@ -0,0 +1,78 @@
+//
+// UsbVolume.cs
+//
+// Author:
+//   Alan McGovern <amcgovern novell com>
+//
+// Copyright (c) 2010 Moonlight Team
+//
+// 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.
+
+#if ENABLE_GIO_HARDWARE
+
+using System;
+using Banshee.Hardware;
+
+namespace Banshee.Hardware.Gio
+{
+    class UsbVolume : Volume, IUsbDevice
+    {
+        public static new IDevice Resolve (IDevice device)
+        {
+            var raw = device as IRawDevice;
+            if (raw != null) {
+                if (UsbDevice.Resolve (device) != null && Volume.Resolve (device) != null)
+                    return new UsbVolume ((RawVolume) raw.Device);
+            }
+            return null;
+        }
+
+        public int BusNumber {
+            get { return UsbDevice.GetBusNumber (this); }
+        }
+
+        public int DeviceNumber {
+            get { return UsbDevice.GetDeviceNumber (this); }
+        }
+
+        public int ProductId {
+            get {return UsbDevice.GetProductId (this); }
+        }
+
+        public double Speed {
+            get { return UsbDevice.GetSpeed (this); }
+        }
+
+        public int VendorId {
+            get { return UsbDevice.GetVendorId (this); }
+        }
+
+        public double Version {
+            get { return UsbDevice.GetVersion(this); }
+        }
+
+        public UsbVolume (RawVolume volume)
+            : base (volume)
+        {
+
+        }
+    }
+}
+
+#endif
diff --git a/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/Volume.cs b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/Volume.cs
new file mode 100644
index 0000000..50f3610
--- /dev/null
+++ b/src/Backends/Banshee.Gio/Banshee.Hardware.Gio/Volume.cs
@@ -0,0 +1,106 @@
+//
+// Volume.cs
+//
+// Author:
+//   Alan McGovern <amcgovern novell com>
+//
+// Copyright (c) 2010 Moonlight Team
+//
+// 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.
+
+#if ENABLE_GIO_HARDWARE
+using System;
+using Banshee.Hardware;
+
+namespace Banshee.Hardware.Gio
+{
+    class Volume : Device, IVolume
+    {
+        RawVolume volume;
+
+        public static new IVolume Resolve (IDevice device)
+        {
+            var raw = device as IRawDevice;
+            if (raw != null && raw.Device is RawVolume) {
+                return new Volume (raw.Device);
+            }
+            return null;
+        }
+
+        public string DeviceNode {
+            get { return device.DeviceNode; }
+        }
+
+        public string MountPoint {
+            get { return volume.MountPoint; }
+        }
+
+        public bool IsReadOnly {
+            get { return volume.IsReadOnly; }
+        }
+
+        public ulong Capacity {
+            get { return volume.Capacity; }
+        }
+
+        public long Available {
+            get { return volume.Available; }
+        }
+
+        public IBlockDevice Parent {
+            get {
+                return BlockDevice.Resolve (this);
+            }
+        }
+
+        public bool ShouldIgnore {
+            get { return false; }
+        }
+
+        public string FileSystem {
+            get { return volume.FileSystem; }
+        }
+
+        public bool CanEject {
+            get { return volume.CanEject; }
+        }
+
+        public bool CanUnmount {
+            get { return volume.CanUnmount; }
+        }
+
+        public Volume (RawDevice device)
+            : base (device)
+        {
+            volume = (RawVolume) device;
+        }
+
+        public void Eject ()
+        {
+            volume.Eject ();
+        }
+
+        public void Unmount ()
+        {
+            volume.Unmount ();
+        }
+    }
+}
+
+#endif
diff --git a/src/Backends/Banshee.Gio/Makefile.am b/src/Backends/Banshee.Gio/Makefile.am
index d24a437..5eeea97 100644
--- a/src/Backends/Banshee.Gio/Makefile.am
+++ b/src/Backends/Banshee.Gio/Makefile.am
@@ -3,7 +3,31 @@ TARGET = library
 LINK = $(REF_BACKEND_GIO)
 INSTALL_DIR = $(BACKENDS_INSTALL_DIR)
 
+if ENABLE_GIO_HARDWARE
+GMCS_FLAGS += "-define:ENABLE_GIO_HARDWARE"
+endif
+
 SOURCES =  \
+	Banshee.Hardware.Gio/BlockDevice.cs \
+	Banshee.Hardware.Gio/CdromDevice.cs \
+	Banshee.Hardware.Gio/Device.cs \
+	Banshee.Hardware.Gio/DeviceMediaCapabilities.cs \
+	Banshee.Hardware.Gio/DiscVolume.cs \
+	Banshee.Hardware.Gio/DiskDevice.cs \
+	Banshee.Hardware.Gio/HardwareManager.cs \
+	Banshee.Hardware.Gio/UsbDevice.cs \
+	Banshee.Hardware.Gio/UsbVolume.cs \
+	Banshee.Hardware.Gio/Volume.cs \
+	Banshee.Hardware.Gio/LowLevel/GioDriveMetadetaSource.cs \
+	Banshee.Hardware.Gio/LowLevel/GioMetadataSource.cs \
+	Banshee.Hardware.Gio/LowLevel/GioVolumeMetadataSource.cs \
+	Banshee.Hardware.Gio/LowLevel/IMetadataSource.cs \
+	Banshee.Hardware.Gio/LowLevel/IRawDevice.cs \
+	Banshee.Hardware.Gio/LowLevel/Manager.cs \
+	Banshee.Hardware.Gio/LowLevel/RawBlockDevice.cs \
+	Banshee.Hardware.Gio/LowLevel/RawDevice.cs \
+	Banshee.Hardware.Gio/LowLevel/RawVolume.cs \
+	Banshee.Hardware.Gio/LowLevel/UdevMetadataSource.cs \
 	Banshee.IO.Gio/DemuxVfs.cs \
 	Banshee.IO.Gio/Directory.cs \
 	Banshee.IO.Gio/File.cs \
diff --git a/src/Backends/Banshee.Hal/Banshee.HalBackend/UsbDevice.cs b/src/Backends/Banshee.Hal/Banshee.HalBackend/UsbDevice.cs
index 206c7d5..c0f58b3 100644
--- a/src/Backends/Banshee.Hal/Banshee.HalBackend/UsbDevice.cs
+++ b/src/Backends/Banshee.Hal/Banshee.HalBackend/UsbDevice.cs
@@ -49,6 +49,14 @@ namespace Banshee.HalBackend
         {
         }
 
+        public int BusNumber {
+            get { return HalDevice.GetPropertyInteger ("usb.bus_number"); }
+        }
+
+        public int DeviceNumber {
+            get { return HalDevice.GetPropertyInteger ("usb.linux.device_number"); }
+        }
+
         public int VendorId {
             get { return HalDevice.GetPropertyInteger ("usb_device.vendor_id"); }
         }
diff --git a/src/Backends/Banshee.Hal/Hal/Manager.cs b/src/Backends/Banshee.Hal/Hal/Manager.cs
index 6544251..218a965 100644
--- a/src/Backends/Banshee.Hal/Hal/Manager.cs
+++ b/src/Backends/Banshee.Hal/Hal/Manager.cs
@@ -122,7 +122,6 @@ namespace Hal
         {
             if(!Bus.System.NameHasOwner("org.freedesktop.Hal")) {
                 // try to start it
-                Console.WriteLine ("About to try to start HAL service");
                 var reply = Bus.System.StartServiceByName ("org.freedesktop.Hal");
                 if (reply != StartReply.Success && reply != StartReply.AlreadyRunning) {
                     throw new ApplicationException("Could not start org.freedesktop.Hal");
@@ -148,14 +147,16 @@ namespace Hal
 
         protected virtual void OnDeviceAdded(string udi)
         {
-            if(DeviceAdded != null)
+            if(DeviceAdded != null) {
                 DeviceAdded(this, new DeviceAddedArgs(udi));
+            }
         }
 
         protected virtual void OnDeviceRemoved(string udi)
         {
-            if(DeviceRemoved != null)
+            if(DeviceRemoved != null) {
                 DeviceRemoved(this, new DeviceRemovedArgs(udi));
+            }
         }
 
         protected virtual void OnNewCapability(string udi, string capability)
diff --git a/src/Backends/Banshee.Hal/Makefile.am b/src/Backends/Banshee.Hal/Makefile.am
index 9ab35e4..454ba29 100644
--- a/src/Backends/Banshee.Hal/Makefile.am
+++ b/src/Backends/Banshee.Hal/Makefile.am
@@ -20,6 +20,10 @@ SOURCES =  \
 
 RESOURCES = Banshee.Hal.addin.xml
 
+if ENABLE_HAL
 include $(top_srcdir)/build/build.mk
+else
+EXTRA_DIST = $(SOURCES) $(RESOURCES)
+endif
 
 
diff --git a/src/Backends/Makefile.am b/src/Backends/Makefile.am
index f1593a0..c0d5c41 100644
--- a/src/Backends/Makefile.am
+++ b/src/Backends/Makefile.am
@@ -1,9 +1,9 @@
 SUBDIRS = \
-	Banshee.Hal \
 	Banshee.Gio \
 	Banshee.Gnome \
 	Banshee.GStreamer \
 	Banshee.GStreamerSharp \
+	Banshee.Hal \
 	Banshee.Unix \
 	Banshee.NowPlaying.X11 \
 	Banshee.Osx
diff --git a/src/Core/Banshee.Services/Banshee.Hardware/HardwareManager.cs b/src/Core/Banshee.Services/Banshee.Hardware/HardwareManager.cs
index d88a7e1..774ed94 100644
--- a/src/Core/Banshee.Services/Banshee.Hardware/HardwareManager.cs
+++ b/src/Core/Banshee.Services/Banshee.Hardware/HardwareManager.cs
@@ -48,7 +48,7 @@ namespace Banshee.Hardware
         {
             var extensions = Banshee.IO.Provider.GetOrderedExtensions (
                 "/Banshee/Platform/HardwareManager",
-                "Banshee.GioBackend.HardwareManager", "Banshee.HalBackend.HardwareManager"
+                "Banshee.Hardware.Gio", "Banshee.HalBackend.HardwareManager"
             );
 
             foreach (var node in extensions) {
diff --git a/src/Core/Banshee.Services/Banshee.Hardware/IUsbDevice.cs b/src/Core/Banshee.Services/Banshee.Hardware/IUsbDevice.cs
index 3dafb00..b6549e0 100644
--- a/src/Core/Banshee.Services/Banshee.Hardware/IUsbDevice.cs
+++ b/src/Core/Banshee.Services/Banshee.Hardware/IUsbDevice.cs
@@ -32,6 +32,8 @@ namespace Banshee.Hardware
 {
     public interface IUsbDevice : IDevice
     {
+        int BusNumber { get; }
+        int DeviceNumber { get; }
         int ProductId { get; }
         int VendorId { get; }
         double Speed { get; }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]