diff --git a/src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp/MtpSource.cs b/src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp/MtpSource.cs
index 1d00c7a..455d1c8 100644
--- a/src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp/MtpSource.cs
+++ b/src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp/MtpSource.cs
@@ -48,10 +48,18 @@ namespace Banshee.Dap.Mtp
 {
     public class MtpSource : DapSource
     {
+        private static List<RawMtpDevice> devices;
 
-        protected override object InternalLock {
-            get { return mtp_device; }
+        public override bool CanConnect {
+            get { return !mtp_volume.IsMounted && mtp_raw != null; }
         }
+
+        public override bool IsConnected {
+            get { return mtp_device != null; }
+        }
+
+        private IVolume mtp_volume;
+        private RawMtpDevice mtp_raw;
         private MtpDevice mtp_device;
 
         //private bool supports_jpegs = false;
@@ -75,7 +83,6 @@ namespace Banshee.Dap.Mtp
             //int busnum = portInfo.BusNumber;
             int devnum = portInfo.DeviceNumber;
 
-            List<RawMtpDevice> devices = null;
             try {
                 devices = MtpDevice.Detect ();
             } catch (TypeInitializationException e) {
@@ -91,33 +98,30 @@ namespace Banshee.Dap.Mtp
                 throw new InvalidDeviceException ();
             }
 
-            IVolume volume = device as IVolume;
-            foreach (var v in devices) {
-                // Using the HAL hardware backend, HAL says the busnum is 2, but libmtp says it's 0, so disabling that check
-                //if (v.BusNumber == busnum && v.DeviceNumber == devnum) {
-                if (v.DeviceNumber == devnum) {
-                    // If gvfs-gphoto has it mounted, unmount it
-                    if (volume != null && volume.IsMounted) {
-                        volume.Unmount ();
-                    }
+            mtp_volume = device as IVolume;
+            mtp_raw = devices.Find (x => x.DeviceNumber == devnum);
 
-                    for (int i = 5; i > 0 && mtp_device == null; i--) {
-                        try {
-                            mtp_device = MtpDevice.Connect (v);
-                        } catch (Exception) {}
+            if (mtp_raw == null) {
+                throw new InvalidDeviceException ();
+            }
+        }
 
-                        if (mtp_device == null) {
-                            Log.DebugFormat ("Failed to connect to mtp device. Trying {0} more times...", i - 1);
-                            Thread.Sleep (2000);
-                        }
+        protected override void TryDeviceConnect ()
+        {
+            lock (InternalLock) {
+                try {
+                    if (CanConnect && !IsConnected) {
+                        mtp_device = MtpDevice.Connect (mtp_raw);
                     }
+                } catch (Exception ex) {
+                    Log.Exception (ex);
                 }
-            }
 
-            if (mtp_device == null) {
-                throw new InvalidDeviceException ();
+                if (mtp_device == null) {
+                    Log.DebugFormat ("Dap.Mtp: deferring MTP device connection");
+                    return;
+                }
             }
-
             // libmtp sometimes returns '?????'. I assume this is if the device does
             // not supply a friendly name. In this case show the model name.
             if (string.IsNullOrEmpty (mtp_device.Name) || mtp_device.Name == "?????")
@@ -125,8 +129,6 @@ namespace Banshee.Dap.Mtp
             else
                 Name = mtp_device.Name;
 
-            Initialize ();
-
             List<string> mimetypes = new List<string> ();
             foreach (FileType format in mtp_device.GetFileTypes ()) {
                 if (format == FileType.JPEG) {
@@ -154,7 +156,7 @@ namespace Banshee.Dap.Mtp
             track_map = new Dictionary<long, Track> ();
             try {
                 List<Track> files = null;
-                lock (mtp_device) {
+                lock (InternalLock) {
                     files = mtp_device.GetAllTracks (delegate (ulong current, ulong total, IntPtr data) {
                         //user_event.Progress = (double)current / total;
                         // Translators: {0} is the name of the MTP audio device (eg Gabe's Zen Player), {1} is the
@@ -169,7 +171,7 @@ namespace Banshee.Dap.Mtp
                 }*/
 
                 // Delete any empty albums
-                lock (mtp_device) {
+                lock (InternalLock) {
                     foreach (Album album in mtp_device.GetAlbums ()) {
                         if (album.Count == 0) {
                             album.Remove ();
@@ -193,7 +195,7 @@ namespace Banshee.Dap.Mtp
                     @"INSERT INTO CorePlaylistEntries (PlaylistID, TrackID)
                         SELECT ?, TrackID FROM CoreTracks WHERE PrimarySourceID = ? AND ExternalID = ?");
 
-                lock (mtp_device) {
+                lock (InternalLock) {
                     var playlists = mtp_device.GetPlaylists ();
                     if (playlists != null) {
                         foreach (MTP.Playlist playlist in playlists) {
@@ -235,7 +237,7 @@ namespace Banshee.Dap.Mtp
 
         public override void SyncPlaylists ()
         {
-            lock (mtp_device) {
+            lock (InternalLock) {
                 List<MTP.Playlist> device_playlists = new List<MTP.Playlist> (mtp_device.GetPlaylists ());
                 foreach (MTP.Playlist playlist in device_playlists) {
                     playlist.Remove ();
@@ -271,7 +273,7 @@ namespace Banshee.Dap.Mtp
             // Hack to get the disk usage indicate to be accurate, which seems to
             // only be updated when tracks are added, not removed.
             try {
-                lock (mtp_device) {
+                lock (InternalLock) {
                     using (System.IO.TextWriter writer = new System.IO.StreamWriter (Banshee.IO.File.OpenWrite (empty_file, true))) {
                         writer.Write ("foo");
                     }
@@ -288,7 +290,7 @@ namespace Banshee.Dap.Mtp
         public override void Rename (string newName)
         {
             base.Rename (newName);
-            lock (mtp_device) {
+            lock (InternalLock) {
                 mtp_device.Name = newName;
             }
         }
@@ -336,7 +338,7 @@ namespace Banshee.Dap.Mtp
             if (track.PrimarySourceId == DbId)
                 return;
 
-            lock (mtp_device) {
+            lock (InternalLock) {
                 Track mtp_track = TrackInfoToMtpTrack (track, fromUri);
                 bool video = track.HasAttribute (TrackMediaAttributes.VideoStream);
                 mtp_device.UploadTrack (fromUri.LocalPath, mtp_track, GetFolderForTrack (track), OnUploadProgress);
@@ -403,7 +405,7 @@ namespace Banshee.Dap.Mtp
 
         protected override bool DeleteTrack (DatabaseTrackInfo track)
         {
-            lock (mtp_device) {
+            lock (InternalLock) {
                 Track mtp_track = track_map [track.TrackId];
                 track_map.Remove (track.TrackId);
 
@@ -441,20 +443,19 @@ namespace Banshee.Dap.Mtp
             disposed = true;
             base.Dispose ();
 
-            if (mtp_device != null) {
-                lock (mtp_device) {
-                    mtp_device.Dispose ();
-                }
-            }
-
-            ServiceManager.SourceManager.RemoveSource (this);
-            mtp_device = null;
         }
 
         protected override void Eject ()
         {
             base.Eject ();
-            Dispose ();
+
+            lock (InternalLock) {
+                if (mtp_device != null) {
+                    mtp_device.Dispose ();
+
+                    mtp_device = null;
+                }
+            }
         }
 
         private static string MakeAlbumKey (string album_artist, string album)
diff --git a/src/Dap/Banshee.Dap/Banshee.Dap.Gui/DapContent.cs b/src/Dap/Banshee.Dap/Banshee.Dap.Gui/DapContent.cs
index 81c5349..1834e6a 100644
--- a/src/Dap/Banshee.Dap/Banshee.Dap.Gui/DapContent.cs
+++ b/src/Dap/Banshee.Dap/Banshee.Dap.Gui/DapContent.cs
@@ -159,4 +159,43 @@ namespace Banshee.Dap.Gui
 
         private static Banshee.Gui.BansheeActionGroup actions;
     }
+
+    public class InactiveContent : ISourceContents
+    {
+        HBox box;
+        DapSource source;
+
+        public InactiveContent (DapSource dapSource)
+        {
+            source = dapSource;
+            var label = string.Format ("<b>Device {0} - {1} Unavailable...</b>",
+                source.Device.Product, source.Device.Name);
+
+            box = new HBox(false, 2);
+            box.PackStart (new Image { IconName = "dialog-warning" }, false, false, 20u);
+            box.PackStart (new Label { Text = label, UseMarkup = true }, false, false, 20u);
+            box.ShowAll ();
+        }
+
+        #region ISourceContents implementation
+        public bool SetSource (ISource source)
+        {
+            return false;
+        }
+        public void ResetSource ()
+        {
+
+        }
+        public ISource Source {
+            get {
+                return source;
+            }
+        }
+        public Gtk.Widget Widget {
+            get {
+                return box;
+            }
+        }
+        #endregion
+    }
 }
diff --git a/src/Dap/Banshee.Dap/Banshee.Dap/DapService.cs b/src/Dap/Banshee.Dap/Banshee.Dap/DapService.cs
index 7ceb59b..a887be9 100644
--- a/src/Dap/Banshee.Dap/Banshee.Dap/DapService.cs
+++ b/src/Dap/Banshee.Dap/Banshee.Dap/DapService.cs
@@ -154,7 +154,7 @@ namespace Banshee.Dap
                 try {
                     DapSource source = (DapSource)node.CreateInstance ();
                     source.DeviceInitialize (device);
-                    source.LoadDeviceContents ();
+                    source.DeviceConnect ();
                     source.AddinId = node.Addin.Id;
                     return source;
                 } catch (InvalidDeviceException) {
@@ -297,7 +297,13 @@ namespace Banshee.Dap
 
         private void OnHardwareDeviceChanged (object o, DeviceChangedArgs args)
         {
-            MapDevice (args.Device);
+            IDevice device = args.Device;
+            DapSource source;
+            if (!sources.TryGetValue (device.Uuid, out source)) {
+                return;
+            }
+
+            source.DeviceConnect ();
         }
 
         private void OnHardwareDeviceRemoved (object o, DeviceRemovedArgs args)
diff --git a/src/Dap/Banshee.Dap/Banshee.Dap/DapSource.cs b/src/Dap/Banshee.Dap/Banshee.Dap/DapSource.cs
index 2f1cabc..ce4513f 100644
--- a/src/Dap/Banshee.Dap/Banshee.Dap/DapSource.cs
+++ b/src/Dap/Banshee.Dap/Banshee.Dap/DapSource.cs
@@ -38,6 +38,7 @@ using Hyena.Data.Sqlite;
 
 using Banshee.ServiceStack;
 using Banshee.Sources;
+using Banshee.Sources.Gui;
 using Banshee.Collection;
 using Banshee.Playlist;
 using Banshee.Collection.Database;
@@ -94,6 +95,28 @@ namespace Banshee.Dap
             TypeUniqueId = device.Serial;
         }
 
+        public void DeviceConnect ()
+        {
+            TryDeviceConnect ();
+
+            Initialize ();
+            ThreadAssist.ProxyToMain ( () => {
+                ISourceContents contents;
+                if (IsConnected) {
+                    contents = new DapContent (this);
+                    LoadDeviceContents ();
+                } else {
+                    contents = new InactiveContent (this);
+                    ClearChildSources ();
+                }
+                Properties.Set<ISourceContents> ("Nereid.SourceContents", contents);
+            });
+        }
+
+        protected virtual void TryDeviceConnect()
+        {
+        }
+
         private object internal_lock = new object ();
         protected virtual object InternalLock {
             get { return internal_lock; }
@@ -110,11 +133,6 @@ namespace Banshee.Dap
                 }
             }
 
-            Flush ();
-
-            PurgeTemporaryPlaylists ();
-            PurgeTracks ();
-
             if (dap_info_bar != null) {
                 var info_bar = dap_info_bar;
                 ThreadAssist.ProxyToMain (info_bar.Destroy);
@@ -240,8 +258,6 @@ namespace Banshee.Dap
             ThreadAssist.ProxyToMain (delegate {
                 dap_info_bar = new DapInfoBar (this);
                 Properties.Set<Gtk.Widget> ("Nereid.SourceContents.FooterWidget", dap_info_bar);
-
-                Properties.Set<Banshee.Sources.Gui.ISourceContents> ("Nereid.SourceContents", new DapContent (this));
             });
         }
 
@@ -295,7 +311,12 @@ namespace Banshee.Dap
 
         public void LoadDeviceContents ()
         {
-            load_thread = ThreadAssist.Spawn (ThreadedLoadDeviceContents);
+            if (IsConnected) {
+                Log.Debug ("Dap: device ready, loading contents...");
+                load_thread = ThreadAssist.Spawn (ThreadedLoadDeviceContents);
+            } else {
+                Log.Debug ("Dap: device not ready");
+            }
         }
 
         private Thread load_thread;
@@ -335,7 +356,14 @@ namespace Banshee.Dap
 
         protected override void Eject ()
         {
+            if (!IsConnected) {
+                return;
+            }
+
             Flush ();
+
+            PurgeTemporaryPlaylists ();
+            PurgeTracks ();
         }
 
         private void Flush ()
@@ -459,6 +487,14 @@ namespace Banshee.Dap
 
 #region Device Properties
 
+        public virtual bool CanConnect {
+            get { return true; }
+        }
+
+        public virtual bool IsConnected {
+            get { return true; }
+        }
+
         protected virtual string [] GetIconNames ()
         {
             string vendor = device.Vendor;
