diff --git a/Banshee.sln b/Banshee.sln
index 4e3d4ca..3d445e2 100644
--- a/Banshee.sln
+++ b/Banshee.sln
@@ -63,6 +63,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Banshee.NowPlaying", "src\E
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Banshee.Lastfm", "src\Extensions\Banshee.Lastfm\Banshee.Lastfm.csproj", "{02FD8195-9796-4AF5-A9D2-D310721963F4}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Banshee.LibraryWatcher", "src\Extensions\Banshee.LibraryWatcher\Banshee.LibraryWatcher.csproj", "{49CA3F27-0BB6-428d-8B3A-20232493652E}"
+EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Banshee.Wikipedia", "src\Extensions\Banshee.Wikipedia\Banshee.Wikipedia.csproj", "{BF5D1722-269B-452E-B577-AEBA0CB894BA}"
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Banshee.PlayQueue", "src\Extensions\Banshee.PlayQueue\Banshee.PlayQueue.csproj", "{74B2E4CC-2701-4C8B-A11D-6E4443F4B21B}"
@@ -227,6 +229,8 @@ Global
 		{EABA3019-7539-4430-9935-D36CEA96F250}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{F38B53BA-8F85-4DC6-9B94-029C1CF96F24}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{F38B53BA-8F85-4DC6-9B94-029C1CF96F24}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{49CA3F27-0BB6-428d-8B3A-20232493652E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{49CA3F27-0BB6-428d-8B3A-20232493652E}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{FCC1AE87-E10B-4B47-8ADE-D5F447E48518}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{FCC1AE87-E10B-4B47-8ADE-D5F447E48518}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{BB1D1D81-7A74-4183-B7B1-3E78B32D42F1}.Debug|Any CPU.Build.0 = Debug|Any CPU
@@ -289,6 +293,8 @@ Global
 		{0130499B-8A93-4CD9-8F3C-593B231609C7}.Windows|Any CPU.ActiveCfg = Windows|Any CPU
 		{F38B53BA-8F85-4DC6-9B94-029C1CF96F24}.Windows|Any CPU.Build.0 = Windows|Any CPU
 		{F38B53BA-8F85-4DC6-9B94-029C1CF96F24}.Windows|Any CPU.ActiveCfg = Windows|Any CPU
+		{49CA3F27-0BB6-428d-8B3A-20232493652E}.Windows|Any CPU.Build.0 = Windows|Any CPU
+		{49CA3F27-0BB6-428d-8B3A-20232493652E}.Windows|Any CPU.ActiveCfg = Windows|Any CPU
 		{FCC1AE87-E10B-4B47-8ADE-D5F447E48518}.Windows|Any CPU.Build.0 = Windows|Any CPU
 		{FCC1AE87-E10B-4B47-8ADE-D5F447E48518}.Windows|Any CPU.ActiveCfg = Windows|Any CPU
 		{46AD1892-C5D3-4696-BA40-FBF7F4CE2B39}.Windows|Any CPU.Build.0 = Windows|Any CPU
@@ -369,6 +375,7 @@ Global
 		{16FB0D3A-53FA-4B8E-B02B-4AF66E87829A} = {4DD1DE63-F20B-4FC3-8FDA-F0BDF4183722}
 		{0130499B-8A93-4CD9-8F3C-593B231609C7} = {4DD1DE63-F20B-4FC3-8FDA-F0BDF4183722}
 		{F38B53BA-8F85-4DC6-9B94-029C1CF96F24} = {4DD1DE63-F20B-4FC3-8FDA-F0BDF4183722}
+		{49CA3F27-0BB6-428d-8B3A-20232493652E} = {4DD1DE63-F20B-4FC3-8FDA-F0BDF4183722}
 		{FCC1AE87-E10B-4B47-8ADE-D5F447E48518} = {4DD1DE63-F20B-4FC3-8FDA-F0BDF4183722}
 		{46AD1892-C5D3-4696-BA40-FBF7F4CE2B39} = {4DD1DE63-F20B-4FC3-8FDA-F0BDF4183722}
 		{6FF6F049-9DAB-48A7-BC4B-F7F3ED0EBA63} = {4DD1DE63-F20B-4FC3-8FDA-F0BDF4183722}
diff --git a/build/build.environment.mk b/build/build.environment.mk
index 6bce1c1..25a4abb 100644
--- a/build/build.environment.mk
+++ b/build/build.environment.mk
@@ -124,6 +124,7 @@ REF_EXTENSION_COVERART = $(LINK_BANSHEE_THICKCLIENT_DEPS)
 REF_EXTENSION_DAAP = $(LINK_BANSHEE_THICKCLIENT_DEPS) $(LINK_ICSHARP_ZIP_LIB) $(LINK_MONO_ZEROCONF)
 REF_EXTENSION_FILESYSTEMQUEUE = $(LINK_BANSHEE_THICKCLIENT_DEPS)
 REF_EXTENSION_INTERNETRADIO = $(LINK_BANSHEE_THICKCLIENT_DEPS)
+REF_EXTENSION_LIBRARYWATCHER = $(LINK_BANSHEE_SERVICES_DEPS)
 REF_EXTENSION_MINIMODE = $(LINK_BANSHEE_THICKCLIENT_DEPS)
 REF_EXTENSION_MULTIMEDIAKEYS = $(LINK_BANSHEE_SERVICES_DEPS)
 REF_EXTENSION_NOTIFICATIONAREA = $(LINK_BANSHEE_THICKCLIENT_DEPS)
diff --git a/configure.ac b/configure.ac
index 7f63678..118d431 100644
--- a/configure.ac
+++ b/configure.ac
@@ -274,6 +274,7 @@ src/Extensions/Banshee.Daap/Makefile
 src/Extensions/Banshee.FileSystemQueue/Makefile
 src/Extensions/Banshee.InternetRadio/Makefile
 src/Extensions/Banshee.Lastfm/Makefile
+src/Extensions/Banshee.LibraryWatcher/Makefile
 src/Extensions/Banshee.MediaWeb/Makefile
 src/Extensions/Banshee.MiniMode/Makefile
 src/Extensions/Banshee.MultimediaKeys/Makefile
diff --git a/src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs b/src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs
index f19049f..286724f 100644
--- a/src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs
+++ b/src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs
@@ -335,7 +335,7 @@ namespace Banshee.Sources
             OnTracksChanged ();
         }
 
-        internal void NotifyTracksDeleted ()
+        public void NotifyTracksDeleted ()
         {
             OnTracksDeleted ();
         }
diff --git a/src/Extensions/Banshee.LibraryWatcher/Banshee.LibraryWatcher.addin.xml b/src/Extensions/Banshee.LibraryWatcher/Banshee.LibraryWatcher.addin.xml
new file mode 100644
index 0000000..421c7d8
--- /dev/null
+++ b/src/Extensions/Banshee.LibraryWatcher/Banshee.LibraryWatcher.addin.xml
@@ -0,0 +1,22 @@
+<Addin
+    id="Banshee.LibraryWatcher"
+    version="1.0"
+    compatVersion="1.0"
+    copyright="© 2008-2009 Christian Martellini, Alexander Hixon, Alexander Kojevnikov. Licensed under the MIT X11 license."
+    name="Library Watcher"
+    category="Hardware"
+    description="Automatically update music and video libraries"
+    author="Christian Martellini, Alexander Hixon, Alexander Kojevnikov"
+    url="http://banshee-project.org/"
+    defaultEnabled="true">
+
+  <Dependencies>
+    <Addin id="Banshee.Services" version="1.0"/>
+    <Addin id="Banshee.ThickClient" version="1.0"/>
+  </Dependencies>
+
+  <Extension path="/Banshee/ServiceManager/Service">
+    <Service class="Banshee.LibraryWatcher.LibraryWatcherService"/>
+  </Extension>
+
+</Addin>
diff --git a/src/Extensions/Banshee.LibraryWatcher/Banshee.LibraryWatcher.csproj b/src/Extensions/Banshee.LibraryWatcher/Banshee.LibraryWatcher.csproj
new file mode 100644
index 0000000..95eed62
--- /dev/null
+++ b/src/Extensions/Banshee.LibraryWatcher/Banshee.LibraryWatcher.csproj
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.50727</ProductVersion>
+    <ProjectGuid>{49CA3F27-0BB6-428d-8B3A-20232493652E}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <UseParentDirectoryAsNamespace>true</UseParentDirectoryAsNamespace>
+    <AssemblyName>Banshee.LibraryWatcher</AssemblyName>
+    <SchemaVersion>2.0</SchemaVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>..\..\..\bin</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
+    <CustomCommands>
+      <CustomCommands>
+        <Command type="Build" command="make" workingdir="${SolutionDir}" />
+        <Command type="Execute" command="make run" workingdir="${SolutionDir}" />
+      </CustomCommands>
+    </CustomCommands>
+    <AssemblyKeyFile>.</AssemblyKeyFile>
+  </PropertyGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\Core\Banshee.Core\Banshee.Core.csproj">
+      <Project>{2ADB831A-A050-47D0-B6B9-9C19D60233BB}</Project>
+      <Name>Banshee.Core</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\Core\Banshee.Services\Banshee.Services.csproj">
+      <Project>{B28354F0-BA87-44E8-989F-B864A3C7C09F}</Project>
+      <Name>Banshee.Services</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\Libraries\Hyena\Hyena.csproj">
+      <Project>{95374549-9553-4C1E-9D89-667755F90E12}</Project>
+      <Name>Hyena</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\Core\Banshee.ThickClient\Banshee.ThickClient.csproj">
+      <Project>{AC839523-7BDF-4AB6-8115-E17921B96EC6}</Project>
+      <Name>Banshee.ThickClient</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="Mono.Addins, Version=0.4.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756" />
+    <Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Banshee.LibraryWacher.addin.xml" />
+    <EmbeddedResource Include="Resources\ActiveSourceUI.xml">
+      <LogicalName>ActiveSourceUI.xml</LogicalName>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Resources\GlobalUI.xml">
+      <LogicalName>GlobalUI.xml</LogicalName>
+    </EmbeddedResource>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Banshee.LibraryWatcher\LibraryWatcherService.cs" />
+    <Compile Include="Banshee.LibraryWatcher\SourceWatcher.cs" />
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <ProjectExtensions>
+    <MonoDevelop>
+      <Properties>
+        <MonoDevelop.Autotools.MakefileInfo IntegrationEnabled="true" RelativeMakefileName="./Makefile.am">
+          <BuildFilesVar Sync="true" Name="SOURCES" />
+          <DeployFilesVar />
+          <ResourcesVar Sync="true" Name="RESOURCES" />
+          <OthersVar />
+          <GacRefVar />
+          <AsmRefVar />
+          <ProjectRefVar />
+        </MonoDevelop.Autotools.MakefileInfo>
+      </Properties>
+    </MonoDevelop>
+  </ProjectExtensions>
+</Project>
diff --git a/src/Extensions/Banshee.LibraryWatcher/Banshee.LibraryWatcher/LibraryWatcherService.cs b/src/Extensions/Banshee.LibraryWatcher/Banshee.LibraryWatcher/LibraryWatcherService.cs
new file mode 100644
index 0000000..fee1aed
--- /dev/null
+++ b/src/Extensions/Banshee.LibraryWatcher/Banshee.LibraryWatcher/LibraryWatcherService.cs
@@ -0,0 +1,120 @@
+//
+// LibraryWatcherService.cs
+//
+// Authors:
+//   Alexander Hixon <hixon.alexander@mediati.org>
+//   Christian Martellini <christian.martellini@gmail.com>
+//
+// Copyright (C) 2008 Alexander Hixon
+// Copyright (C) 2009 Christian Martellini
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections.Generic;
+
+using Banshee.Base ;
+using Banshee.Sources;
+using Banshee.ServiceStack;
+using Banshee.Library;
+
+namespace Banshee.LibraryWatcher
+{
+    public class LibraryWatcherService : IExtensionService, IDisposable, IDelayedInitializeService
+    {
+        private readonly Dictionary<LibrarySource, SourceWatcher> watchers =
+            new Dictionary<LibrarySource, SourceWatcher> ();
+
+        string IService.ServiceName {
+            get { return "LibraryWatcherService"; }
+        }
+
+        void IExtensionService.Initialize ()
+        {
+        }
+
+        public void DelayedInitialize ()
+        {
+            ServiceManager.SourceManager.SourceAdded += OnSourceAdded;
+            ServiceManager.SourceManager.SourceRemoved += OnSourceRemoved;
+
+            foreach (var library in ServiceManager.SourceManager.FindSources<LibrarySource> ()) {
+                AddLibrary (library);
+            }
+        }
+
+        public void Dispose ()
+        {
+            lock (watchers) {
+                foreach (var watcher in watchers.Values) {
+                    watcher.Dispose ();
+                }
+                watchers.Clear ();
+            }
+        }
+
+        private void OnSourceAdded (SourceAddedArgs args)
+        {
+            var library = args.Source as LibrarySource;
+            if (library != null) {
+                AddLibrary (library);
+            }
+        }
+
+        private void OnSourceRemoved (SourceEventArgs args)
+        {
+            var library = args.Source as LibrarySource;
+            if (library != null) {
+                RemoveLibrary (library);
+            }
+        }
+
+        private void AddLibrary (LibrarySource library)
+        {
+            if (!Banshee.IO.Directory.Exists(library.BaseDirectoryWithSeparator)) {
+                Hyena.Log.DebugFormat ("Will not watch library {0} because its folder doesn't exist: {1}",
+                    library.Name, library.BaseDirectoryWithSeparator);
+                return;
+            }
+            lock (watchers) {
+                if (!watchers.ContainsKey (library)) {
+                    try {
+                        watchers[library] = new SourceWatcher (library);
+                        Hyena.Log.DebugFormat ("Started LibraryWatcher for {0} ({1})",
+                            library.Name, library.BaseDirectoryWithSeparator);
+                    } catch (Exception e) {
+                        Hyena.Log.Exception (e);
+                    }
+                }
+            }
+        }
+
+        private void RemoveLibrary (LibrarySource library)
+        {
+            lock (watchers) {
+                if (watchers.ContainsKey (library)) {
+                    watchers[library].Dispose ();
+                    watchers.Remove (library);
+                }
+            }
+        }
+    }
+}
diff --git a/src/Extensions/Banshee.LibraryWatcher/Banshee.LibraryWatcher/SourceWatcher.cs b/src/Extensions/Banshee.LibraryWatcher/Banshee.LibraryWatcher/SourceWatcher.cs
new file mode 100644
index 0000000..5bc0c3f
--- /dev/null
+++ b/src/Extensions/Banshee.LibraryWatcher/Banshee.LibraryWatcher/SourceWatcher.cs
@@ -0,0 +1,239 @@
+//
+// SourceWatcher.cs
+//
+// Authors:
+//   Christian Martellini <christian.martellini@gmail.com>
+//   Alexander Kojevnikov <alexander@kojevnikov.com>
+//
+// Copyright (C) 2009 Christian Martellini
+// Copyright (C) 2009 Alexander Kojevnikov
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.IO;
+using System.Data;
+using System.Threading;
+using System.Collections.Generic;
+
+using Banshee.Base;
+using Banshee.Library;
+using Banshee.Sources;
+using Banshee.ServiceStack;
+using Banshee.Collection.Database;
+
+using Hyena;
+using Hyena.Data.Sqlite;
+
+namespace Banshee.LibraryWatcher
+{
+    public class SourceWatcher : IDisposable
+    {
+        private readonly LibraryImportManager import_manager;
+        private readonly LibrarySource library;
+        private readonly FileSystemWatcher watcher;
+        private readonly ManualResetEvent handle;
+        private readonly Thread watch_thread;
+
+        private readonly Queue<QueueItem> queue = new Queue<QueueItem> ();
+        private readonly TimeSpan delay = TimeSpan.FromMilliseconds (2000);
+
+        private bool active;
+        private bool disposed;
+
+        private class QueueItem
+        {
+            public DateTime When;
+            public WatcherChangeTypes ChangeType;
+            public string OldFullPath;
+            public string FullPath;
+        }
+
+        public SourceWatcher (LibrarySource library)
+        {
+            this.library = library;
+            handle = new ManualResetEvent(false);
+            string path = library.BaseDirectoryWithSeparator;
+            string home = Environment.GetFolderPath (Environment.SpecialFolder.Personal) + Path.DirectorySeparatorChar;
+            if (path == home) {
+                throw new Exception ("Will not create LibraryWatcher for the entire home directory");
+            }
+
+            import_manager = ServiceManager.Get<LibraryImportManager> ();
+
+            watcher = new FileSystemWatcher (path);
+            watcher.IncludeSubdirectories = true;
+            watcher.Created += OnChanged;
+            watcher.Deleted += OnChanged;
+            watcher.Renamed += OnChanged;
+
+            active = true;
+            watch_thread = new Thread (new ThreadStart (Watch));
+            watch_thread.Name = String.Format ("LibraryWatcher for {0}", library.Name);
+            watch_thread.IsBackground = true;
+            watch_thread.Start ();
+        }
+
+#region Public Methods
+
+        public void Dispose ()
+        {
+            if (!disposed) {
+                watcher.EnableRaisingEvents = false;
+                active = false;
+                watcher.Created -= OnChanged;
+                watcher.Deleted -= OnChanged;
+                watcher.Renamed -= OnChanged;
+
+                watcher.Dispose ();
+                disposed = true;
+            }
+        }
+
+#endregion
+
+#region Private Methods
+
+        private void OnChanged (object source, FileSystemEventArgs args)
+        {
+            var item = new QueueItem {
+                When = DateTime.Now,
+                ChangeType = args.ChangeType,
+                FullPath = args.FullPath,
+                OldFullPath = args is RenamedEventArgs ? ((RenamedEventArgs)args).OldFullPath : args.FullPath
+            };
+            lock (queue) {
+                queue.Enqueue (item);
+            }
+            Hyena.Log.DebugFormat ("Watcher: {0} {1}{2}",
+                item.ChangeType, args is RenamedEventArgs ? item.OldFullPath + " => " : "", item.FullPath);
+            handle.Set ();
+        }
+
+        private void Watch ()
+        {
+            watcher.EnableRaisingEvents = true;
+
+            while (active) {
+                WatcherChangeTypes change_types = 0;
+                while (queue.Count > 0) {
+                    QueueItem item;
+                    lock (queue) {
+                        item = queue.Dequeue ();
+                    }
+
+                    int sleep =  (int) (item.When + delay - DateTime.Now).TotalMilliseconds;
+                    if (sleep > 0) {
+                        Hyena.Log.DebugFormat ("Watcher: sleeping {0}ms", sleep);
+                        Thread.Sleep (sleep);
+                    }
+
+                    if (item.ChangeType == WatcherChangeTypes.Created) {
+                        AddTrack (item.FullPath);
+                    } else if (item.ChangeType == WatcherChangeTypes.Deleted) {
+                        RemoveTrack (item.FullPath);
+                    } else if (item.ChangeType == WatcherChangeTypes.Renamed) {
+                        RenameTrack (item.OldFullPath, item.FullPath);
+                    }
+
+                    change_types |= item.ChangeType;
+                }
+
+                if ((change_types & WatcherChangeTypes.Deleted) > 0) {
+                    library.NotifyTracksDeleted ();
+                }
+                if ((change_types & (WatcherChangeTypes.Renamed | WatcherChangeTypes.Created)) > 0) {
+                    library.NotifyTracksChanged ();
+                }
+
+                handle.WaitOne ();
+                handle.Reset ();
+            }
+        }
+
+        private void AddTrack (string track)
+        {
+            import_manager.ImportTrack (track);
+
+            // Trigger file rename.
+            string uri = new SafeUri(track).AbsoluteUri;
+            HyenaSqliteCommand command = new HyenaSqliteCommand (@"
+                UPDATE CoreTracks
+                SET DateUpdatedStamp = LastSyncedStamp + 1
+                WHERE Uri = ?", uri);
+            ServiceManager.DbConnection.Execute (command);
+        }
+
+        private static readonly char[] escaped_chars = new char[] {'\\', '%', '_'};
+        private void RemoveTrack (string track)
+        {
+            string uri = new SafeUri(track).AbsoluteUri;
+            int track_id = DatabaseTrackInfo.GetTrackIdForUri (uri);
+
+            const string delete_sql = @"
+                INSERT INTO CoreRemovedTracks (DateRemovedStamp, TrackID, Uri)
+                SELECT ?, TrackID, Uri FROM CoreTracks WHERE TrackID IN ({0})
+                ;
+                DELETE FROM CoreTracks WHERE TrackID IN ({0})";
+
+            // If track_id is 0, it's a directory.
+            HyenaSqliteCommand delete_command;
+            if (track_id > 0) {
+                delete_command = new HyenaSqliteCommand (String.Format (delete_sql,
+                    "?"), DateTime.Now, track_id, track_id);
+            } else {
+                string pattern = uri;
+                if (pattern.IndexOfAny (escaped_chars) != -1) {
+                    pattern = pattern.Replace (@"\", @"\\").Replace ("%", @"\%").Replace ("_", @"\_");
+                }
+                pattern += "/_%";
+
+                delete_command = new HyenaSqliteCommand (String.Format (delete_sql,
+                    @"SELECT TrackID FROM CoreTracks WHERE Uri LIKE ? ESCAPE '\'"), DateTime.Now, pattern, pattern);
+            }
+
+            ServiceManager.DbConnection.Execute (delete_command);
+        }
+
+        private void RenameTrack(string oldFullPath, string fullPath)
+        {
+            if (oldFullPath == fullPath) {
+                // FIXME: bug in mono, bnc#322330 looks similar but not exactly
+                return;
+            }
+            string old_uri = new SafeUri (oldFullPath).AbsoluteUri;
+            string new_uri = new SafeUri (fullPath).AbsoluteUri;
+            string pattern = old_uri;
+            if (pattern.IndexOfAny (escaped_chars) != -1) {
+                pattern = pattern.Replace (@"\", @"\\").Replace ("%", @"\%").Replace ("_", @"\_");
+            }
+            pattern += "%";
+            HyenaSqliteCommand rename_command = new HyenaSqliteCommand (@"
+                UPDATE CoreTracks
+                SET Uri = REPLACE(Uri, ?, ?), DateUpdatedStamp = ?
+                WHERE Uri LIKE ? ESCAPE '\'",
+                old_uri, new_uri, DateTime.Now, pattern);
+            ServiceManager.DbConnection.Execute (rename_command);
+        }
+
+#endregion
+    }
+}
diff --git a/src/Extensions/Banshee.LibraryWatcher/Makefile.am b/src/Extensions/Banshee.LibraryWatcher/Makefile.am
new file mode 100644
index 0000000..67d22fe
--- /dev/null
+++ b/src/Extensions/Banshee.LibraryWatcher/Makefile.am
@@ -0,0 +1,13 @@
+ASSEMBLY = Banshee.LibraryWatcher
+TARGET = library
+LINK = $(REF_EXTENSION_LIBRARYWATCHER)
+INSTALL_DIR = $(EXTENSIONS_INSTALL_DIR)
+
+SOURCES =  \
+	Banshee.LibraryWatcher/LibraryWatcherService.cs \
+	Banshee.LibraryWatcher/SourceWatcher.cs
+
+RESOURCES = Banshee.LibraryWatcher.addin.xml
+
+include $(top_srcdir)/build/build.mk
+
diff --git a/src/Extensions/Makefile.am b/src/Extensions/Makefile.am
index caef9f9..cdf1298 100644
--- a/src/Extensions/Makefile.am
+++ b/src/Extensions/Makefile.am
@@ -8,6 +8,7 @@ SUBDIRS = \
 	Banshee.FileSystemQueue \
 	Banshee.InternetRadio \
 	Banshee.Lastfm \
+	Banshee.LibraryWatcher \
 	Banshee.MiniMode \
 	Banshee.MultimediaKeys \
 	Banshee.NotificationArea \
@@ -21,4 +22,5 @@ SUBDIRS = \
 	Banshee.RemoteAudio \
 	Banshee.Wikipedia
 
+
 MAINTAINERCLEANFILES = Makefile.in
