diff --git a/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackInfo.cs b/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackInfo.cs
index 1b5f984..59c7e4a 100644
--- a/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackInfo.cs
+++ b/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackInfo.cs
@@ -727,6 +727,66 @@ namespace Banshee.Collection.Database
             }
         }
 
+        private static SafeUri CreateAvailableDuplicateFilename (string filename)
+        {
+            SafeUri uri = new SafeUri (filename);
+            string extension = Path.GetExtension (filename);
+            string filename_no_ext = filename.Remove (filename.Length - extension.Length);
+            int duplicate_index = 1;
+            while (Banshee.IO.File.Exists (uri)) {
+                filename = String.Format ("{0} ({1}){2}", filename_no_ext, duplicate_index, extension);
+                uri = new SafeUri (filename);
+                duplicate_index++;
+            }
+
+            return uri;
+        }
+
+
+        public bool MoveToLibraryIfAppropriate ()
+        {
+            bool move_success = true;
+
+            LibrarySource library_source = PrimarySource as LibrarySource;
+            if (library_source == null) {
+                // Get out, not a local Library
+                return false;
+            }
+
+            SafeUri old_uri = this.Uri;
+            if (old_uri == null) {
+                // Get out quick, no URI set yet.
+                return move_success;
+            }
+
+            bool in_library = old_uri.IsLocalPath ? old_uri.AbsolutePath.StartsWith (PrimarySource.BaseDirectoryWithSeparator) : false;
+            if (!in_library && library_source.HasMoveFiles && library_source.MoveFiles) {
+                string new_filename = PathPattern.BuildFull (PrimarySource.BaseDirectory, this, Path.GetExtension (old_uri.ToString ()));
+                SafeUri new_uri = new SafeUri (new_filename);
+
+                try {
+                    if (Banshee.IO.File.Exists (new_uri)) {
+                        if (Banshee.IO.File.GetSize (old_uri) == Banshee.IO.File.GetSize (new_uri)) {
+                            Hyena.Log.DebugFormat ("Not copying {0} to library because there is already a file of same size at {1}", old_uri, new_uri);
+                            move_success = false;
+                            return move_success;
+                        } else {
+                            new_uri = CreateAvailableDuplicateFilename (new_filename);
+                        }
+                    }
+
+                    Banshee.IO.File.Move (old_uri, new_uri);
+                    Banshee.IO.Utilities.TrimEmptyDirectories (old_uri);
+
+                    Uri = new_uri;
+                } catch (Exception e) {
+                    Log.ErrorFormat ("Exception moving into library: {0}", e);
+                }
+            }
+
+            return move_success;
+        }
+
         public bool CopyToLibraryIfAppropriate (bool force_copy)
         {
             bool copy_success = true;
diff --git a/src/Core/Banshee.Services/Banshee.Library/LibrarySource.cs b/src/Core/Banshee.Services/Banshee.Library/LibrarySource.cs
index 7a4a0fc..8af403a 100644
--- a/src/Core/Banshee.Services/Banshee.Library/LibrarySource.cs
+++ b/src/Core/Banshee.Services/Banshee.Library/LibrarySource.cs
@@ -188,6 +188,19 @@ namespace Banshee.Library
                 if (!(source is LibrarySource)) {
                     track.CopyToLibraryIfAppropriate (false);
                 }
+                else {
+                    LibrarySource oldSource = source as LibrarySource;
+                    if (oldSource.MoveFiles) {
+                        if (track.MoveToLibraryIfAppropriate ()) {
+                            Log.InformationFormat ("'{0}' moved to {1}", new Object[] { track.ToString(), this.ToString() });
+                        }
+                    } else {
+                        // For now, files are only moved if old source and new source are
+                        // configured to move files (new source is checked in 
+                        // MoveToLibraryIfAppropriate, as it's done in CopyToLibrary...).
+                        Log.InformationFormat ("{0} doesn't allow file move.", oldSource);
+                    }
+                }
 
                 track.Save (false);
 
diff --git a/src/Core/Banshee.Services/Banshee.Metadata/SaveTrackMetadataJob.cs b/src/Core/Banshee.Services/Banshee.Metadata/SaveTrackMetadataJob.cs
index dfeb3a6..2539d8c 100644
--- a/src/Core/Banshee.Services/Banshee.Metadata/SaveTrackMetadataJob.cs
+++ b/src/Core/Banshee.Services/Banshee.Metadata/SaveTrackMetadataJob.cs
@@ -47,8 +47,6 @@ namespace Banshee.Metadata
 {
     public class SaveTrackMetadataJob : DbIteratorJob
     {
-        private LibrarySource musicLibrarySource = ServiceManager.SourceManager.MusicLibrary;
-
         public SaveTrackMetadataJob () : base (Catalog.GetString ("Saving Metadata to File"))
         {
             SetResources (Resource.Cpu, Resource.Disk, Resource.Database);
@@ -126,13 +124,18 @@ namespace Banshee.Metadata
         private bool RenameFile (DatabaseTrackInfo track)
         {
             SafeUri old_uri = track.Uri;
-            bool in_library = old_uri.AbsolutePath.StartsWith (musicLibrarySource.BaseDirectoryWithSeparator);
+            if (!(track.PrimarySource is LibrarySource)) {
+                return false;
+            }
+
+            string base_directory = (track.PrimarySource as LibrarySource).BaseDirectoryWithSeparator;
+            bool in_library = old_uri.AbsolutePath.StartsWith (base_directory);
 
             if (!in_library) {
                 return false;
             }
 
-            string new_filename = track.PathPattern.BuildFull (musicLibrarySource.BaseDirectory, track, System.IO.Path.GetExtension (old_uri.ToString ()));
+            string new_filename = track.PathPattern.BuildFull (base_directory, track, System.IO.Path.GetExtension (old_uri.ToString ()));
             SafeUri new_uri = new SafeUri (new_filename);
 
             if (!new_uri.Equals (old_uri) && !Banshee.IO.File.Exists (new_uri)) {
diff --git a/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceView_DragAndDrop.cs b/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceView_DragAndDrop.cs
index a5a9a31..a18e0f2 100644
--- a/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceView_DragAndDrop.cs
+++ b/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceView_DragAndDrop.cs
@@ -239,6 +239,16 @@ namespace Banshee.Sources.Gui
                         ServiceManager.SourceManager.ActiveSource,
                         from_filter ? SourceMergeType.Source : SourceMergeType.ModelSelection
                     );
+
+                    // Update sources to reflect changes in gui and enable file move to new location
+                    if (ServiceManager.SourceManager.ActiveSource is LibrarySource) {
+                        (ServiceManager.SourceManager.ActiveSource as LibrarySource).NotifyTracksChanged ();
+                    }
+
+                    if (drop_source is LibrarySource) {
+                        (drop_source as LibrarySource).NotifyTracksChanged ();
+                    }
+
                 } else {
                     Hyena.Log.DebugFormat ("SourceView got unknown drag target type: {0}", data.Target.Name);
                 }
diff --git a/src/Extensions/Banshee.Audiobook/Banshee.Audiobook/AudiobookLibrarySource.cs b/src/Extensions/Banshee.Audiobook/Banshee.Audiobook/AudiobookLibrarySource.cs
index 9335fc0..91a36fe 100644
--- a/src/Extensions/Banshee.Audiobook/Banshee.Audiobook/AudiobookLibrarySource.cs
+++ b/src/Extensions/Banshee.Audiobook/Banshee.Audiobook/AudiobookLibrarySource.cs
@@ -384,6 +384,10 @@ namespace Banshee.Audiobook
             get { return false; }
         }
 
+        public override bool HasMoveFiles {
+            get { return true; }
+        }
+
         protected override bool HasArtistAlbum {
             get { return false; }
         }
