[banshee] 2009-04-16 Gabriel Burt <gabriel burt gmail com>



commit eb659bf73654010cfd4c37b2c68c8c4ad12197db
Author: Gabriel Burt <gabriel burt gmail com>
Date:   Thu Apr 16 17:08:39 2009 -0500

    2009-04-16 Gabriel Burt <gabriel burt gmail com>
    
    This patch adds separate library folder preferences for Music Library,
    	Video Library, and Podcasts (BGO #404827).  They are all configurable via
    	the Preferences dialog.  It also changes the format used to store URIs in
    	the database, from sometime relative and sometimes absolute to always
    	absolute (BGO #564355).
    
    	* src/Core/Banshee.Core/Banshee.Base/FileNamePattern.cs:
    	* src/Core/Banshee.Core/Banshee.Base/Paths.cs:
    	* src/Core/Banshee.Core/Banshee.Configuration.Schema/LibrarySchema.cs:
    	* src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseImportManager.cs:
    	* src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackInfo.cs:
    	* src/Core/Banshee.Services/Banshee.Collection/MoveOnInfoSaveJob.cs:
    	* src/Core/Banshee.Services/Banshee.Collection/RescanPipeline.cs:
    	* src/Core/Banshee.Services/Banshee.Database/BansheeDbFormatMigrator.cs:
    	* src/Core/Banshee.Services/Banshee.Library/LibrarySource.cs:
    	* src/Core/Banshee.Services/Banshee.Library/MusicLibrarySource.cs:
    	* src/Core/Banshee.Services/Banshee.Library/VideoLibrarySource.cs:
    	* src/Core/Banshee.Services/Banshee.Playlist/PlaylistFileUtil.cs:
    	* src/Core/Banshee.Services/Banshee.Preferences/SourcePage.cs:
    	* src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs:
    	* src/Core/Banshee.Services/Makefile.am:
    	* src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/TrackEditorDialog.cs:
    	* src/Core/Banshee.ThickClient/Banshee.Gui/GlobalActions.cs:
    	* src/Core/Banshee.ThickClient/Banshee.Gui/SourceActions.cs:
    	* src/Core/Banshee.ThickClient/Banshee.Preferences.Gui/DefaultPreferenceWidgets.cs:
    	* src/Core/Banshee.ThickClient/Banshee.Preferences.Gui/NotebookPage.cs:
    	* src/Core/Banshee.ThickClient/Banshee.Preferences.Gui/PageComboBox.cs:
    	* src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/MassStorageSource.cs:
    	* src/Extensions/Banshee.AudioCd/Banshee.AudioCd/AudioCdRipper.cs:
    	* src/Extensions/Banshee.Bpm/Banshee.Bpm/BpmDetectJob.cs:
    	* src/Extensions/Banshee.CoverArt/Banshee.CoverArt/CoverArtJob.cs:
    	* src/Extensions/Banshee.FileSystemQueue/Banshee.FileSystemQueue/FileSystemQueueSource.cs:
    	* src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueSource.cs:
    	* src/Extensions/Banshee.PlayerMigration/Banshee.PlayerMigration/RhythmboxPlayerImportSource.cs:
    	* src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Data/PodcastSource.cs:
    	* src/Extensions/Banshee.Podcasting/Banshee.Podcasting/PodcastService.cs:
    	* src/Extensions/Banshee.Podcasting/Banshee.Podcasting/PodcastService_Interface.cs:
    	* src/Extensions/Banshee.Podcasting/Resources/GlobalUI.xml:
    	* src/Libraries/Migo/Migo.Syndication/FeedsManager.cs:
    	* src/Core/Banshee.Services/Banshee.Library/LibraryLocationPreference.cs:
    	Remove assumptions about there being only one Library Location, instead
    	use the relevant PrimarySource's BaseDirectory.  Remove relative-URI
    	logic/munging; always use the absolute URI.  Add library location
    	preferences for Music, Video, and Podcasts.
---
 ChangeLog                                          |   47 +++++++++
 .../Banshee.Core/Banshee.Base/FileNamePattern.cs   |    8 +-
 src/Core/Banshee.Core/Banshee.Base/Paths.cs        |   37 -------
 .../Banshee.Configuration.Schema/LibrarySchema.cs  |   45 +--------
 .../DatabaseImportManager.cs                       |    2 +-
 .../DatabaseTrackInfo.cs                           |   99 +++++---------------
 .../Banshee.Collection/MoveOnInfoSaveJob.cs        |   13 ++-
 .../Banshee.Collection/RescanPipeline.cs           |   35 ++++---
 .../Banshee.Database/BansheeDbFormatMigrator.cs    |   32 ++++++-
 .../Banshee.Library/LibraryLocationPreference.cs   |   51 ----------
 .../Banshee.Library/LibrarySource.cs               |   50 +++++++---
 .../Banshee.Library/MusicLibrarySource.cs          |   22 +++--
 .../Banshee.Library/VideoLibrarySource.cs          |    4 +
 .../Banshee.Playlist/PlaylistFileUtil.cs           |    2 +-
 .../Banshee.Preferences/SourcePage.cs              |   28 +++++-
 .../Banshee.Sources/PrimarySource.cs               |   29 +++----
 src/Core/Banshee.Services/Makefile.am              |    1 -
 .../Banshee.Gui.TrackEditor/TrackEditorDialog.cs   |    2 +-
 .../Banshee.Gui/GlobalActions.cs                   |    5 +-
 .../Banshee.Gui/SourceActions.cs                   |    2 +-
 .../DefaultPreferenceWidgets.cs                    |   38 ++++++--
 .../Banshee.Preferences.Gui/NotebookPage.cs        |    1 -
 .../Banshee.Preferences.Gui/PageComboBox.cs        |   13 ++-
 .../Banshee.Dap.MassStorage/MassStorageSource.cs   |    2 +-
 .../Banshee.AudioCd/AudioCdRipper.cs               |    2 +-
 .../Banshee.Bpm/Banshee.Bpm/BpmDetectJob.cs        |    8 +-
 .../Banshee.CoverArt/CoverArtJob.cs                |    4 +-
 .../FileSystemQueueSource.cs                       |    6 +-
 .../Banshee.PlayQueue/PlayQueueSource.cs           |    2 +-
 .../RhythmboxPlayerImportSource.cs                 |    2 +-
 .../Banshee.Podcasting.Data/PodcastSource.cs       |   22 ++--
 .../Banshee.Podcasting/PodcastService.cs           |   52 +++++++----
 .../Banshee.Podcasting/PodcastService_Interface.cs |    6 +-
 .../Banshee.Podcasting/Resources/GlobalUI.xml      |    2 +
 .../Migo/Migo.Syndication/FeedsManager.cs          |    1 +
 35 files changed, 322 insertions(+), 353 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index a3d4199..d77b497 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,50 @@
+2009-04-16  Gabriel Burt  <gabriel burt gmail com>
+
+	This patch adds separate library folder preferences for Music Library,
+	Video Library, and Podcasts (BGO #404827).  They are all configurable via
+	the Preferences dialog.  It also changes the format used to store URIs in
+	the database, from sometime relative and sometimes absolute to always
+	absolute (BGO #564355).
+
+	* src/Core/Banshee.Core/Banshee.Base/FileNamePattern.cs:
+	* src/Core/Banshee.Core/Banshee.Base/Paths.cs:
+	* src/Core/Banshee.Core/Banshee.Configuration.Schema/LibrarySchema.cs:
+	* src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseImportManager.cs:
+	* src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackInfo.cs:
+	* src/Core/Banshee.Services/Banshee.Collection/MoveOnInfoSaveJob.cs:
+	* src/Core/Banshee.Services/Banshee.Collection/RescanPipeline.cs:
+	* src/Core/Banshee.Services/Banshee.Database/BansheeDbFormatMigrator.cs:
+	* src/Core/Banshee.Services/Banshee.Library/LibrarySource.cs:
+	* src/Core/Banshee.Services/Banshee.Library/MusicLibrarySource.cs:
+	* src/Core/Banshee.Services/Banshee.Library/VideoLibrarySource.cs:
+	* src/Core/Banshee.Services/Banshee.Playlist/PlaylistFileUtil.cs:
+	* src/Core/Banshee.Services/Banshee.Preferences/SourcePage.cs:
+	* src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs:
+	* src/Core/Banshee.Services/Makefile.am:
+	* src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/TrackEditorDialog.cs:
+	* src/Core/Banshee.ThickClient/Banshee.Gui/GlobalActions.cs:
+	* src/Core/Banshee.ThickClient/Banshee.Gui/SourceActions.cs:
+	* src/Core/Banshee.ThickClient/Banshee.Preferences.Gui/DefaultPreferenceWidgets.cs:
+	* src/Core/Banshee.ThickClient/Banshee.Preferences.Gui/NotebookPage.cs:
+	* src/Core/Banshee.ThickClient/Banshee.Preferences.Gui/PageComboBox.cs:
+	* src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/MassStorageSource.cs:
+	* src/Extensions/Banshee.AudioCd/Banshee.AudioCd/AudioCdRipper.cs:
+	* src/Extensions/Banshee.Bpm/Banshee.Bpm/BpmDetectJob.cs:
+	* src/Extensions/Banshee.CoverArt/Banshee.CoverArt/CoverArtJob.cs:
+	* src/Extensions/Banshee.FileSystemQueue/Banshee.FileSystemQueue/FileSystemQueueSource.cs:
+	* src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueSource.cs:
+	* src/Extensions/Banshee.PlayerMigration/Banshee.PlayerMigration/RhythmboxPlayerImportSource.cs:
+	* src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Data/PodcastSource.cs:
+	* src/Extensions/Banshee.Podcasting/Banshee.Podcasting/PodcastService.cs:
+	* src/Extensions/Banshee.Podcasting/Banshee.Podcasting/PodcastService_Interface.cs:
+	* src/Extensions/Banshee.Podcasting/Resources/GlobalUI.xml:
+	* src/Libraries/Migo/Migo.Syndication/FeedsManager.cs:
+	* src/Core/Banshee.Services/Banshee.Library/LibraryLocationPreference.cs:
+	Remove assumptions about there being only one Library Location, instead
+	use the relevant PrimarySource's BaseDirectory.  Remove relative-URI
+	logic/munging; always use the absolute URI.  Add library location
+	preferences for Music, Video, and Podcasts.
+
 2009-04-16  Aaron Bockover  <abock gnome org>
 
 	* Project: migrated to git, repository structure cleaned up and
diff --git a/src/Core/Banshee.Core/Banshee.Base/FileNamePattern.cs b/src/Core/Banshee.Core/Banshee.Base/FileNamePattern.cs
index 613c824..2a15c9f 100644
--- a/src/Core/Banshee.Core/Banshee.Base/FileNamePattern.cs
+++ b/src/Core/Banshee.Core/Banshee.Base/FileNamePattern.cs
@@ -249,12 +249,12 @@ namespace Banshee.Base
             return OnFilter (repl_pattern);
         }
 
-        public static string BuildFull (TrackInfo track)
+        public static string BuildFull (string base_dir, TrackInfo track)
         {
-            return BuildFull (track, Path.GetExtension (track.Uri.ToString ()));
+            return BuildFull (base_dir, track, Path.GetExtension (track.Uri.ToString ()));
         }
 
-        public static string BuildFull (ITrackInfo track, string ext)
+        public static string BuildFull (string base_dir, ITrackInfo track, string ext)
         {
             if (ext == null || ext.Length < 1) {
                 ext = String.Empty;
@@ -264,7 +264,7 @@ namespace Banshee.Base
             
             string songpath = CreateFromTrackInfo (track) + ext;
             songpath = Hyena.StringUtil.EscapePath (songpath);
-            string dir = Path.GetFullPath (Path.Combine (Paths.LibraryLocation, 
+            string dir = Path.GetFullPath (Path.Combine (base_dir, 
                 Path.GetDirectoryName (songpath)));
             string filename = Path.Combine (dir, Path.GetFileName (songpath));
                 
diff --git a/src/Core/Banshee.Core/Banshee.Base/Paths.cs b/src/Core/Banshee.Core/Banshee.Base/Paths.cs
index b79e9ee..c96b5e2 100644
--- a/src/Core/Banshee.Core/Banshee.Base/Paths.cs
+++ b/src/Core/Banshee.Core/Banshee.Base/Paths.cs
@@ -161,10 +161,6 @@ namespace Banshee.Base
         public static string ExtensionCacheRoot {
             get { return Path.Combine (ApplicationCache, "extensions"); }
         }
-        
-        public static string DefaultLibraryPath {
-            get { return XdgBaseDirectorySpec.GetUserDirectory ("XDG_MUSIC_DIR", "Music"); }
-        }
 
         public static string SystemTempDir {
             get { return "/tmp/"; }
@@ -183,39 +179,6 @@ namespace Banshee.Base
             }
         }
         
-        private static string cached_library_location;
-        private static string cached_library_location_with_separator;
-        public static string LibraryLocation {
-             get {
-                string path = LibrarySchema.Location.Get (Paths.DefaultLibraryPath);
-                if (String.IsNullOrEmpty (path)) {
-                    path = Paths.DefaultLibraryPath;
-                }
-                
-                LibraryLocation = path;
-                return cached_library_location;
-             }
-             
-             set {
-                cached_library_location = value;
-                cached_library_location_with_separator = null;
-                LibrarySchema.Location.Set (cached_library_location); 
-            }
-        }
-        
-        public static string CachedLibraryLocation {
-            get { return cached_library_location ?? LibraryLocation; }
-        }
-        
-        public static string CachedLibraryLocationWithSeparator {
-            get {
-                if (cached_library_location_with_separator == null) {
-                    cached_library_location_with_separator = CachedLibraryLocation + Path.DirectorySeparatorChar;
-                }
-                return cached_library_location_with_separator;
-            }
-        }
-        
         private static string installed_application_prefix = null;
         public static string InstalledApplicationPrefix {
             get {
diff --git a/src/Core/Banshee.Core/Banshee.Configuration.Schema/LibrarySchema.cs b/src/Core/Banshee.Core/Banshee.Configuration.Schema/LibrarySchema.cs
index a79ab75..8030e76 100644
--- a/src/Core/Banshee.Core/Banshee.Configuration.Schema/LibrarySchema.cs
+++ b/src/Core/Banshee.Core/Banshee.Configuration.Schema/LibrarySchema.cs
@@ -33,13 +33,9 @@ namespace Banshee.Configuration.Schema
 {
     public static class LibrarySchema
     {
-        public static readonly SchemaEntry<string> Location = new SchemaEntry<string>(
-            "library", "base_location",
-            String.Empty,
-            "Library location",
-            "Base location for library music"
-        );
-    
+        // Deprecated, don't use in new code
+        internal static readonly SchemaEntry<string> Location = new SchemaEntry<string> ("library", "base_location", null, null, null);
+
         public static readonly SchemaEntry<string> FolderPattern = new SchemaEntry<string>(
             "library", "folder_pattern",
             Banshee.Base.FileNamePattern.DefaultFolder,
@@ -60,27 +56,6 @@ namespace Banshee.Configuration.Schema
                 "%track_count%, %track_number_nz% (No prefixed zero), %track_count_nz% (No prefixed zero), " +
                 "%album_artist_initial%, %artist% (deprecated, use %album_artist%)."
         );
-
-        public static readonly SchemaEntry<int> SortColumn = new SchemaEntry<int>(
-            "library", "sort_column",
-            -1,
-            "Column index",
-            "Column index for sorting the library source. -1 for unset."
-        );
-
-        public static readonly SchemaEntry<int> SortType = new SchemaEntry<int>(
-            "library", "sort_type",
-            0,
-            "Column sort type",
-            "Column sort type for the library source. Ascending (0) or Descending (1)"
-        );
-        
-        public static readonly SchemaEntry<bool> SourceExpanded = new SchemaEntry<bool>(
-            "library", "source_expanded",
-            true,
-            "Library source expansion",
-            "Whether to expand the library node in the source view"
-        );
         
         public static readonly SchemaEntry<bool> CopyOnImport = new SchemaEntry<bool>(
             "library", "copy_on_import",
@@ -102,19 +77,5 @@ namespace Banshee.Configuration.Schema
             "Write metadata back to audio files",
             "If enabled, metadata (tags) will be written back to audio files when using the track metadata editor."
         );
-        
-        public static readonly SchemaEntry<int> PlaylistSortOrder = new SchemaEntry<int>(
-            "library", "playlist_sort_order",
-            0,
-            "Sort order of playlists",
-            "Sort order of library playlists in the source view (0 = Ascending, 1 = Descending)"
-        );
-        
-        public static readonly SchemaEntry<int> PlaylistSortCriteria = new SchemaEntry<int>(
-            "library", "playlist_sort_criteria",
-            0,
-            "Sort criteria of playlists",
-            "Sort criteria of library playlists in the source view (0 = Name, 1 = Size)"
-        );
     }
 }
diff --git a/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseImportManager.cs b/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseImportManager.cs
index 17bf48d..33c8e57 100644
--- a/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseImportManager.cs
+++ b/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseImportManager.cs
@@ -159,7 +159,7 @@ namespace Banshee.Collection.Database
                 return null;
             }
 
-            if (DatabaseTrackInfo.ContainsUri (uri, Paths.MakePathRelative (uri.AbsolutePath, BaseDirectory) ?? uri.AbsoluteUri, PrimarySourceIds)) {
+            if (DatabaseTrackInfo.ContainsUri (uri, PrimarySourceIds)) {
                 // TODO add DatabaseTrackInfo.SyncedStamp property, and if the file has been
                 // updated since the last sync, fetch its metadata into the db.
                 return null;
diff --git a/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackInfo.cs b/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackInfo.cs
index 6f0b4c3..3a3e8c7 100644
--- a/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackInfo.cs
+++ b/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackInfo.cs
@@ -52,12 +52,6 @@ using Banshee.Streaming;
 
 namespace Banshee.Collection.Database
 {
-    public enum TrackUriType : int {
-        AbsolutePath = 0,
-        RelativePath = 1,
-        AbsoluteUri = 2
-    }
-
     public class DatabaseTrackInfo : TrackInfo
     {
         private static DatabaseTrackModelProvider<DatabaseTrackInfo> provider;
@@ -67,7 +61,6 @@ namespace Banshee.Collection.Database
         }
 
         private bool artist_changed = false, album_changed = false;
-        private bool uri_fields_dirty = false;
         
         public DatabaseTrackInfo () : base ()
         {
@@ -191,10 +184,7 @@ namespace Banshee.Collection.Database
         [DatabaseColumn ("PrimarySourceID")]
         public int PrimarySourceId {
             get { return primary_source_id; }
-            set {
-                primary_source_id = value;
-                UpdateUri ();
-            }
+            set { primary_source_id = value; }
         }
 
         public PrimarySource PrimarySource {
@@ -365,46 +355,10 @@ namespace Banshee.Collection.Database
             set { base.MusicBrainzId = value; }
         }
 
-        public override SafeUri Uri {
-            get { return base.Uri; }
-            set {
-                base.Uri = value;
-                uri_fields_dirty = true;
-            }
-        }
-        
-        private string uri_field;
         [DatabaseColumn ("Uri")]
         protected string UriField {
-            get {
-                if (uri_fields_dirty && Uri != null && PrimarySource != null) {
-                    PrimarySource.UriToFields (Uri, out uri_type, out uri_field);
-                    uri_fields_dirty = false;
-                }
-                return uri_field;
-            }
-            set {
-                uri_field = value;
-                UpdateUri ();
-            }
-        }
-        
-        private bool uri_type_set;
-        private TrackUriType uri_type;
-        [DatabaseColumn ("UriType")]
-        protected TrackUriType UriType {
-            get {
-                if (uri_fields_dirty && Uri != null && PrimarySource != null) {
-                    PrimarySource.UriToFields (Uri, out uri_type, out uri_field);
-                    uri_fields_dirty = false;
-                }
-                return uri_type;
-            }
-            set {
-                uri_type = value;
-                uri_type_set = true;
-                UpdateUri ();
-            }
+            get { return Uri.AbsoluteUri; }
+            set { Uri = new SafeUri (value); }
         }
         
         [DatabaseColumn]
@@ -644,13 +598,6 @@ namespace Banshee.Collection.Database
             }
         }
 
-        private void UpdateUri ()
-        {
-            if (Uri == null && uri_type_set && UriField != null && PrimarySource != null) {
-                Uri = PrimarySource.UriAndTypeToSafeUri (UriType, UriField);
-            }
-        }
-
         public void CopyToLibraryIfAppropriate (bool force_copy)
         {
             SafeUri old_uri = this.Uri;
@@ -659,14 +606,15 @@ namespace Banshee.Collection.Database
                 return;
             }
             
-            bool in_library = old_uri.AbsolutePath.StartsWith (Paths.CachedLibraryLocationWithSeparator);
+            bool in_library = old_uri.AbsolutePath.StartsWith (PrimarySource.BaseDirectoryWithSeparator);
 
             if (!in_library && (LibrarySchema.CopyOnImport.Get () || force_copy)) {
-                string new_filename = FileNamePattern.BuildFull (this, Path.GetExtension (old_uri.ToString ()));
+                string new_filename = FileNamePattern.BuildFull (PrimarySource.BaseDirectory, this, Path.GetExtension (old_uri.ToString ()));
                 SafeUri new_uri = new SafeUri (new_filename);
 
                 try {
                     if (Banshee.IO.File.Exists (new_uri)) {
+                        Hyena.Log.DebugFormat ("Not copying {0} to library because there is already a file at {1}", old_uri, new_uri);
                         return;
                     }
                     
@@ -678,34 +626,31 @@ namespace Banshee.Collection.Database
             }
         }
 
-        private static HyenaSqliteCommand check_command = new HyenaSqliteCommand (
-            "SELECT TrackID FROM CoreTracks WHERE PrimarySourceId IN (?) AND (Uri = ? OR Uri = ?) LIMIT 1"
-        );
-
-        public static int GetTrackIdForUri (SafeUri uri, string relative_path, int [] primary_sources)
+        private static HyenaSqliteCommand get_uri_id_cmd = new HyenaSqliteCommand ("SELECT TrackID FROM CoreTracks WHERE Uri = ? LIMIT 1");
+        public static int GetTrackIdForUri (string uri)
         {
-            return ServiceManager.DbConnection.Query<int> (check_command,
-                primary_sources, relative_path, uri.AbsoluteUri);
+            return ServiceManager.DbConnection.Query<int> (get_uri_id_cmd, new SafeUri (uri).AbsoluteUri);
         }
 
-        public static int GetTrackIdForUri (string relative_path, int [] primary_sources)
-        {
-            return GetTrackIdForUri (relative_path, relative_path, primary_sources);
-        }
-        
-        public static int GetTrackIdForUri (string uri, string relative_path, int [] primary_sources)
+        private static HyenaSqliteCommand get_track_id_by_uri = new HyenaSqliteCommand (
+            "SELECT TrackID FROM CoreTracks WHERE PrimarySourceId IN (?) AND Uri = ? LIMIT 1"
+        );
+
+        public static int GetTrackIdForUri (SafeUri uri, int [] primary_sources)
         {
-            return ServiceManager.DbConnection.Query<int> (check_command, primary_sources, uri, relative_path);
+            return ServiceManager.DbConnection.Query<int> (get_track_id_by_uri,
+                primary_sources, uri.AbsoluteUri);
         }
-        
-        public static bool ContainsUri (string relative_path, int [] primary_sources)
+
+        public static int GetTrackIdForUri (string absoluteUri, int [] primary_sources)
         {
-            return GetTrackIdForUri (relative_path, primary_sources) > 0;
+            return ServiceManager.DbConnection.Query<int> (get_track_id_by_uri,
+                primary_sources, absoluteUri);
         }
 
-        public static bool ContainsUri (SafeUri uri, string relative_path, int [] primary_sources)
+        public static bool ContainsUri (SafeUri uri, int [] primary_sources)
         {
-            return GetTrackIdForUri (uri, relative_path, primary_sources) > 0;
+            return GetTrackIdForUri (uri, primary_sources) > 0;
         }
     }
 }
diff --git a/src/Core/Banshee.Services/Banshee.Collection/MoveOnInfoSaveJob.cs b/src/Core/Banshee.Services/Banshee.Collection/MoveOnInfoSaveJob.cs
index 2e77747..a81b12a 100644
--- a/src/Core/Banshee.Services/Banshee.Collection/MoveOnInfoSaveJob.cs
+++ b/src/Core/Banshee.Services/Banshee.Collection/MoveOnInfoSaveJob.cs
@@ -32,38 +32,43 @@ using System.IO;
 using Mono.Unix;
 
 using Banshee.Base;
+using Banshee.Collection.Database;
 using Banshee.Configuration.Schema;
 
 namespace Banshee.Collection
 {
     public class MoveOnInfoSaveJob : Banshee.Kernel.IInstanceCriticalJob
     {
-        private TrackInfo track;
+        private DatabaseTrackInfo track;
 
         public string Name {
             get { return String.Format (Catalog.GetString ("Renaming {0}"), track.TrackTitle); }
         }
 
-        public MoveOnInfoSaveJob (TrackInfo track)
+        public MoveOnInfoSaveJob (DatabaseTrackInfo track)
         {
             this.track = track;
         }
 
         public void Run ()
         {
+            if (track == null) {
+                return;
+            }
+
             if (!LibrarySchema.MoveOnInfoSave.Get ()) {
                 Hyena.Log.Debug ("Skipping scheduled rename, preference disabled after scheduling");
                 return;
             }
 
             SafeUri old_uri = track.Uri;
-            bool in_library = old_uri.AbsolutePath.StartsWith (Paths.CachedLibraryLocationWithSeparator);
+            bool in_library = old_uri.AbsolutePath.StartsWith (track.PrimarySource.BaseDirectoryWithSeparator);
 
             if (!in_library) {
                 return;
             }
 
-            string new_filename = FileNamePattern.BuildFull (track, Path.GetExtension (old_uri.ToString ()));
+            string new_filename = FileNamePattern.BuildFull (track.PrimarySource.BaseDirectory, track, 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.Services/Banshee.Collection/RescanPipeline.cs b/src/Core/Banshee.Services/Banshee.Collection/RescanPipeline.cs
index 23ce488..66aa9c8 100644
--- a/src/Core/Banshee.Services/Banshee.Collection/RescanPipeline.cs
+++ b/src/Core/Banshee.Services/Banshee.Collection/RescanPipeline.cs
@@ -96,17 +96,20 @@ namespace Banshee.Collection
 
             //Hyena.Log.DebugFormat ("Have {0} items before delete", ServiceManager.DbConnection.Query<int>("select count(*) from coretracks where primarysourceid=?", psource.DbId));
 
-            // Delete tracks that are under the BaseDirectory (UriType = relative) and that weren't rescanned just now
-            ServiceManager.DbConnection.Execute (@"BEGIN;
-                DELETE FROM CorePlaylistEntries WHERE TrackID IN 
-                    (SELECT TrackID FROM CoreTracks WHERE PrimarySourceID = ? AND UriType = ? AND LastSyncedStamp IS NOT NULL AND LastSyncedStamp < ?);
-                DELETE FROM CoreSmartPlaylistEntries WHERE TrackID IN
-                    (SELECT TrackID FROM CoreTracks WHERE PrimarySourceID = ? AND UriType = ? AND LastSyncedStamp IS NOT NULL AND LastSyncedStamp < ?);
-                DELETE FROM CoreTracks WHERE PrimarySourceID = ? AND UriType = ? AND LastSyncedStamp IS NOT NULL AND LastSyncedStamp < ?;
-                COMMIT",
-                psource.DbId, (int)TrackUriType.RelativePath, scan_started,
-                psource.DbId, (int)TrackUriType.RelativePath, scan_started,
-                psource.DbId, (int)TrackUriType.RelativePath, scan_started
+            // Delete tracks that are under the BaseDirectory and that weren't rescanned just now
+            string condition = String.Format (
+                "WHERE PrimarySourceID = ? AND Uri LIKE '{0}%' AND LastSyncedStamp IS NOT NULL AND LastSyncedStamp < ?",
+                new SafeUri (psource.BaseDirectoryWithSeparator).AbsoluteUri
+            );
+
+            ServiceManager.DbConnection.Execute (String.Format (@"BEGIN;
+                    DELETE FROM CorePlaylistEntries WHERE TrackID IN (SELECT TrackID FROM CoreTracks {0});
+                    DELETE FROM CoreSmartPlaylistEntries WHERE TrackID IN (SELECT TrackID FROM CoreTracks {0});
+                    DELETE FROM CoreTracks {0}; COMMIT",
+                condition),
+                psource.DbId, scan_started,
+                psource.DbId, scan_started,
+                psource.DbId, scan_started
             );
 
             // TODO prune artists/albums
@@ -133,7 +136,7 @@ namespace Banshee.Collection
             this.scan_started = scan_started;
 
             fetch_command = DatabaseTrackInfo.Provider.CreateFetchCommand (
-                "CoreTracks.PrimarySourceID = ? AND (CoreTracks.Uri = ? OR CoreTracks.Uri = ?) LIMIT 1");
+                "CoreTracks.PrimarySourceID = ? AND CoreTracks.Uri = ? LIMIT 1");
 
             fetch_similar_command = DatabaseTrackInfo.Provider.CreateFetchCommand (
                 "CoreTracks.PrimarySourceID = ? AND CoreTracks.LastSyncedStamp < ? AND CoreTracks.MetadataHash = ?");
@@ -152,9 +155,9 @@ namespace Banshee.Collection
 
             //Hyena.Log.DebugFormat ("Rescanning item {0}", file_path);
             try {
-                string relative_path = Banshee.Base.Paths.MakePathRelative (file_path, psource.BaseDirectory);
+                SafeUri uri = new SafeUri (file_path);
                 
-                IDataReader reader = ServiceManager.DbConnection.Query (fetch_command, psource.DbId, file_path, relative_path);
+                IDataReader reader = ServiceManager.DbConnection.Query (fetch_command, psource.DbId, uri.AbsoluteUri);
                 if (reader.Read () ) {
                     //Hyena.Log.DebugFormat ("Found it in the db!");
                     DatabaseTrackInfo track = DatabaseTrackInfo.Provider.Load (reader);
@@ -168,7 +171,7 @@ namespace Banshee.Collection
                 } else {
                     // This URI is not in the database - try to find it based on MetadataHash in case it was simply moved
                     DatabaseTrackInfo track = new DatabaseTrackInfo ();
-                    Banshee.Streaming.StreamTagger.TrackInfoMerge (track, new SafeUri (file_path));
+                    Banshee.Streaming.StreamTagger.TrackInfoMerge (track, uri);
     
                     IDataReader similar_reader = ServiceManager.DbConnection.Query (fetch_similar_command, psource.DbId, scan_started, track.MetadataHash);
                     DatabaseTrackInfo similar_track = null;
@@ -176,7 +179,7 @@ namespace Banshee.Collection
                         similar_track = DatabaseTrackInfo.Provider.Load (similar_reader);
                         if (!Banshee.IO.File.Exists (similar_track.Uri)) {
                             //Hyena.Log.DebugFormat ("Apparently {0} was moved to {1}", similar_track.Uri, file_path);
-                            similar_track.Uri = new SafeUri (file_path);
+                            similar_track.Uri = uri;
                             MergeIfModified (similar_track);
                             similar_track.LastSyncedStamp = DateTime.Now;
                             similar_track.Save (false);
diff --git a/src/Core/Banshee.Services/Banshee.Database/BansheeDbFormatMigrator.cs b/src/Core/Banshee.Services/Banshee.Database/BansheeDbFormatMigrator.cs
index cf7aa29..f3dc17f 100644
--- a/src/Core/Banshee.Services/Banshee.Database/BansheeDbFormatMigrator.cs
+++ b/src/Core/Banshee.Services/Banshee.Database/BansheeDbFormatMigrator.cs
@@ -3,8 +3,9 @@
 //
 // Author:
 //   Aaron Bockover <abockover novell com>
+//   Gabriel Burt <gburt novell com>
 //
-// Copyright (C) 2007-2008 Novell, Inc.
+// Copyright (C) 2007-2009 Novell, Inc.
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -53,7 +54,7 @@ namespace Banshee.Database
         // NOTE: Whenever there is a change in ANY of the database schema,
         //       this version MUST be incremented and a migration method
         //       MUST be supplied to match the new version number
-        protected const int CURRENT_VERSION = 30;
+        protected const int CURRENT_VERSION = 31;
         protected const int CURRENT_METADATA_VERSION = 6;
         
 #region Migration Driver
@@ -715,6 +716,31 @@ namespace Banshee.Database
 #endregion
 
 
+#region Version 31
+
+        [DatabaseVersion (31)]
+        private bool Migrate_31 ()
+        {
+            try {
+                // Make paths not relative for Music Library items
+                string library_path = Banshee.Library.LibrarySource.OldLocationSchema.Get ();
+                if (library_path != null) {
+                    int podcast_src_id = connection.Query<int> ("SELECT PrimarySourceID FROM CorePrimarySources WHERE StringID = 'PodcastSource-PodcastLibrary'");
+                    
+                    Banshee.Base.SafeUri uri = new Banshee.Base.SafeUri (library_path);
+                    connection.Execute ("UPDATE CoreTracks SET Uri = (? || Uri) WHERE UriType = 1 AND PrimarySourceID != ?", uri.AbsoluteUri + System.IO.Path.DirectorySeparatorChar, podcast_src_id);
+
+                    uri = new Banshee.Base.SafeUri (Banshee.Base.Paths.Combine (library_path, "Podcasts"));
+                    connection.Execute ("UPDATE CoreTracks SET Uri = (? || Uri) WHERE UriType = 1 AND PrimarySourceID = ?", uri.AbsoluteUri + System.IO.Path.DirectorySeparatorChar, podcast_src_id);
+                }
+            } catch (Exception e) {
+                Hyena.Log.Exception (e);
+            }
+            return true;
+        }
+        
+#endregion
+
 #pragma warning restore 0169
         
 #region Fresh database setup
@@ -770,7 +796,6 @@ namespace Banshee.Database
                     MusicBrainzID       TEXT,
 
                     Uri                 TEXT,
-                    UriType             INTEGER,
                     MimeType            TEXT,
                     FileSize            INTEGER,
                     BitRate             INTEGER,
@@ -967,7 +992,6 @@ namespace Banshee.Database
                         0,
                         0,
                         Uri,
-                        0,
                         MimeType,
                         0, 0,
                         {0},
diff --git a/src/Core/Banshee.Services/Banshee.Library/LibraryLocationPreference.cs b/src/Core/Banshee.Services/Banshee.Library/LibraryLocationPreference.cs
deleted file mode 100644
index d8004af..0000000
--- a/src/Core/Banshee.Services/Banshee.Library/LibraryLocationPreference.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-//
-// LibraryLocationPreference.cs
-//
-// Author:
-//   Aaron Bockover <abockover novell com>
-//
-// Copyright (C) 2008 Novell, Inc.
-//
-// 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 Mono.Unix;
-
-using Banshee.Base;
-using Banshee.Preferences;
-
-namespace Banshee.Library
-{
-    public class LibraryLocationPreference : Preference<string>
-    {        
-        public LibraryLocationPreference () : base ("library-location", String.Empty)
-        {
-        }
-        
-        public override string Value {
-            get { return Paths.LibraryLocation; }
-            set {
-                Paths.LibraryLocation = value;
-                OnValueChanged ();
-            }
-        }
-    }
-}
diff --git a/src/Core/Banshee.Services/Banshee.Library/LibrarySource.cs b/src/Core/Banshee.Services/Banshee.Library/LibrarySource.cs
index aefbf0e..31d41b1 100644
--- a/src/Core/Banshee.Services/Banshee.Library/LibrarySource.cs
+++ b/src/Core/Banshee.Services/Banshee.Library/LibrarySource.cs
@@ -39,19 +39,32 @@ using Banshee.Base;
 using Banshee.Sources;
 using Banshee.Database;
 using Banshee.ServiceStack;
+using Banshee.Preferences;
 using Banshee.Collection;
 using Banshee.Collection.Database;
 
 namespace Banshee.Library
 {
-    public class LibrarySource : PrimarySource
+    public abstract class LibrarySource : PrimarySource
     {
+        // Deprecated, don't use in new code
+        internal static readonly Banshee.Configuration.SchemaEntry<string> OldLocationSchema = new Banshee.Configuration.SchemaEntry<string> ("library", "base_location", null, null, null);
+
+        private Banshee.Configuration.SchemaEntry<string> base_dir_schema;
+
         public LibrarySource (string label, string name, int order) : base (label, label, name, order)
         {
             Properties.SetString ("GtkActionPath", "/LibraryContextMenu");
             Properties.SetString ("RemoveTracksActionLabel", Catalog.GetString ("Remove From Library"));
             IsLocal = true;
+            base_dir_schema = CreateSchema<string> ("library-location", null, "The base directory under which files for this library are stored", null);
             AfterInitialized ();
+            
+            Section library_section = PreferencesPage.Add (new Section ("library-location", 
+                // Translators: {0} is the library name, eg 'Music Library' or 'Podcasts'
+                String.Format (Catalog.GetString ("{0} Folder"), Name), 2));
+
+            library_section.Add (base_dir_schema);
         }
 
         public string AttributesCondition {
@@ -76,10 +89,26 @@ namespace Banshee.Library
             set { not_media_types = value; }
         }
 
+        public override string PreferencesPageId {
+            get { return UniqueId; }
+        }
+
         public override string BaseDirectory {
-            get { return Paths.CachedLibraryLocation; }
+            get {
+                string dir = base_dir_schema.Get ();
+                if (dir == null) {
+                    BaseDirectory = dir = DefaultBaseDirectory;
+                }
+                return dir;
+            }
+            protected set {
+                base_dir_schema.Set (value);
+                base.BaseDirectory = value;
+            }
         }
         
+        public abstract string DefaultBaseDirectory { get; }
+        
         public override bool Indexable {
             get { return true; }
         }
@@ -120,11 +149,12 @@ namespace Banshee.Library
                 source.NotifyTracksChanged ();
             } else {
                 // Figure out where we should put it if were to copy it
-                string path = FileNamePattern.BuildFull (track);
+                string path = FileNamePattern.BuildFull (BaseDirectory, track);
                 SafeUri uri = new SafeUri (path);
 
                 // Make sure it's not already in the library
-                if (DatabaseTrackInfo.ContainsUri (uri, Paths.MakePathRelative (uri.AbsolutePath, BaseDirectory) ?? uri.AbsoluteUri, new int [] {DbId})) {
+                // TODO optimize - no need to recrate this int [] every time
+                if (DatabaseTrackInfo.ContainsUri (uri, new int [] {DbId})) {
                     return;
                 }
 
@@ -138,17 +168,5 @@ namespace Banshee.Library
                 new_track.Save (false);
             }
         }
-        
-        public static int GetTrackIdForUri (string uri)
-        {
-            return DatabaseTrackInfo.GetTrackIdForUri (new SafeUri (uri), Paths.MakePathRelative (uri, Paths.LibraryLocation), LibraryIds);
-        }
-        
-        private static int [] library_ids;
-        private static int [] LibraryIds {
-            get {
-                return library_ids ?? (library_ids = new int [] {ServiceManager.SourceManager.MusicLibrary.DbId, ServiceManager.SourceManager.VideoLibrary.DbId});
-            }
-        }
     }
 }
diff --git a/src/Core/Banshee.Services/Banshee.Library/MusicLibrarySource.cs b/src/Core/Banshee.Services/Banshee.Library/MusicLibrarySource.cs
index 9a2afd7..e4cedc0 100644
--- a/src/Core/Banshee.Services/Banshee.Library/MusicLibrarySource.cs
+++ b/src/Core/Banshee.Services/Banshee.Library/MusicLibrarySource.cs
@@ -35,6 +35,7 @@ using Mono.Unix;
 using Banshee.Collection;
 using Banshee.SmartPlaylist;
 using Banshee.Preferences;
+using Banshee.Configuration;
 using Banshee.Configuration.Schema;
 
 namespace Banshee.Library
@@ -46,12 +47,15 @@ namespace Banshee.Library
             MediaTypes = TrackMediaAttributes.Music | TrackMediaAttributes.AudioStream;
             NotMediaTypes = TrackMediaAttributes.Podcast | TrackMediaAttributes.VideoStream | TrackMediaAttributes.AudioBook;
             Properties.SetStringList ("Icon.Name", "audio-x-generic", "source-library");
-            Properties.SetString ("SourcePreferencesActionLabel", Catalog.GetString ("Music Library Preferences"));
-
-            Section library_section = PreferencesPage.Add (new Section ("library-location", 
-                Catalog.GetString ("Music Library Folder"), 2));
-
-            library_section.Add (new LibraryLocationPreference ());
+            
+            // Migrate the old library-location schema, if necessary
+            if (DatabaseConfigurationClient.Client.Get<int> ("MusicLibraryLocationMigrated", 0) != 1) {
+                string old_location = OldLocationSchema.Get ();
+                if (!String.IsNullOrEmpty (old_location)) {
+                    BaseDirectory = old_location;
+                }
+                DatabaseConfigurationClient.Client.Set<int> ("MusicLibraryLocationMigrated", 1);
+            }
 
             Section file_system = PreferencesPage.Add (new Section ("file-system", 
                 Catalog.GetString ("File System Organization"), 5));
@@ -64,9 +68,9 @@ namespace Banshee.Library
 
             PreferencesPage.Add (new Section ("misc", Catalog.GetString ("Miscellaneous"), 10));
         }
-
-        public override string PreferencesPageId {
-            get { return UniqueId; }
+        
+        public override string DefaultBaseDirectory {
+            get { return Banshee.Base.XdgBaseDirectorySpec.GetUserDirectory ("XDG_MUSIC_DIR", "Music"); }
         }
 
         public override IEnumerable<SmartPlaylistDefinition> DefaultSmartPlaylists {
diff --git a/src/Core/Banshee.Services/Banshee.Library/VideoLibrarySource.cs b/src/Core/Banshee.Services/Banshee.Library/VideoLibrarySource.cs
index 1c148af..77434a9 100644
--- a/src/Core/Banshee.Services/Banshee.Library/VideoLibrarySource.cs
+++ b/src/Core/Banshee.Services/Banshee.Library/VideoLibrarySource.cs
@@ -70,6 +70,10 @@ namespace Banshee.Library
         protected override bool HasArtistAlbum {
             get { return false; }
         }
+        
+        public override string DefaultBaseDirectory {
+            get { return Banshee.Base.XdgBaseDirectorySpec.GetUserDirectory ("XDG_VIDEOS_DIR", "Videos"); }
+        }
 
         public override IEnumerable<SmartPlaylistDefinition> DefaultSmartPlaylists {
             get { return default_smart_playlists; }
diff --git a/src/Core/Banshee.Services/Banshee.Playlist/PlaylistFileUtil.cs b/src/Core/Banshee.Services/Banshee.Playlist/PlaylistFileUtil.cs
index 045c9f2..875f410 100644
--- a/src/Core/Banshee.Services/Banshee.Playlist/PlaylistFileUtil.cs
+++ b/src/Core/Banshee.Services/Banshee.Playlist/PlaylistFileUtil.cs
@@ -259,7 +259,7 @@ namespace Banshee.Playlist
                 //ServiceManager.DbConnection.BeginTransaction ();
                 foreach (string uri in uris) {
                     // FIXME: Does the following call work if the source is just a PrimarySource (not LibrarySource)?
-                    int track_id = Banshee.Library.LibrarySource.GetTrackIdForUri (uri);
+                    int track_id = source.GetTrackIdForUri (uri);
                     if (track_id > 0) {
                         ServiceManager.DbConnection.Execute (insert_command, track_id);
                     }
diff --git a/src/Core/Banshee.Services/Banshee.Preferences/SourcePage.cs b/src/Core/Banshee.Services/Banshee.Preferences/SourcePage.cs
index 9c6bf44..8adad38 100644
--- a/src/Core/Banshee.Services/Banshee.Preferences/SourcePage.cs
+++ b/src/Core/Banshee.Services/Banshee.Preferences/SourcePage.cs
@@ -31,17 +31,19 @@ using System;
 using Banshee.ServiceStack;
 using Banshee.Sources;
 
+using Hyena.Data;
+
 namespace Banshee.Preferences
 {
     public class SourcePage : Page, IDisposable
     {
+        private Source source;
+
         public SourcePage (Source source) : this (source.UniqueId, source.Name, null, source.Order)
         {
-            if (source.Properties.GetType ("Icon.Name") == typeof(string)) {
-                IconName = source.Properties.Get<string> ("Icon.Name");
-            } else if (source.Properties.GetType ("Icon.Name") == typeof(string[])) {
-                IconName = source.Properties.Get<string[]> ("Icon.Name")[0];
-            }
+            this.source = source;
+            source.Properties.PropertyChanged += OnPropertyChanged;
+            UpdateIcon ();
         }
 
         public SourcePage (string uniqueId, string name, string iconName, int order) : base (uniqueId, name, order)
@@ -54,5 +56,21 @@ namespace Banshee.Preferences
         {
             ServiceManager.Get<Banshee.Preferences.PreferenceService> ()["source-specific"].ChildPages.Remove (this);
         }
+
+        private void UpdateIcon ()
+        {
+            if (source.Properties.GetType ("Icon.Name") == typeof(string)) {
+                IconName = source.Properties.Get<string> ("Icon.Name");
+            } else if (source.Properties.GetType ("Icon.Name") == typeof(string[])) {
+                IconName = source.Properties.Get<string[]> ("Icon.Name")[0];
+            }
+        }
+
+        private void OnPropertyChanged (object o, PropertyChangeEventArgs args)
+        {
+            if (args.PropertyName == "Icon.Name") {
+                UpdateIcon ();
+            }
+        }
     }
 }
diff --git a/src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs b/src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs
index e3f56d6..ce43fce 100644
--- a/src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs
+++ b/src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs
@@ -200,26 +200,15 @@ namespace Banshee.Sources
         {
             return (primary_sources.ContainsKey (id)) ? primary_sources[id] : null;
         }
-        
-        public virtual SafeUri UriAndTypeToSafeUri (TrackUriType type, string uri_field)
-        {
-            if (type == TrackUriType.RelativePath && BaseDirectory != null)
-                return new SafeUri (System.IO.Path.Combine (BaseDirectory, uri_field));
-            else
-                return new SafeUri (uri_field);
-        }
-
-        public virtual void UriToFields (SafeUri uri, out TrackUriType type, out string uri_field)
-        {
-            uri_field = Paths.MakePathRelative (uri.AbsolutePath, BaseDirectory);
-            type = (uri_field == null) ? TrackUriType.AbsoluteUri : TrackUriType.RelativePath;
-            if (uri_field == null) {
-                uri_field = uri.AbsoluteUri;
-            }
-        }
 
         public virtual string BaseDirectory {
             get { return null; }
+            protected set { base_dir_with_sep = null; }
+        }
+        
+        private string base_dir_with_sep;
+        public string BaseDirectoryWithSeparator {
+            get { return base_dir_with_sep ?? (base_dir_with_sep = BaseDirectory + System.IO.Path.DirectorySeparatorChar); }
         }
 
         protected PrimarySource (string generic_name, string name, string id, int order) : base (generic_name, name, id, order)
@@ -595,6 +584,12 @@ namespace Banshee.Sources
             return true;
         }
 
+        private static HyenaSqliteCommand get_track_id_cmd = new HyenaSqliteCommand ("SELECT TrackID FROM CoreTracks WHERE PrimarySourceId = ? AND Uri = ? LIMIT 1");
+        public int GetTrackIdForUri (string uri)
+        {
+            return ServiceManager.DbConnection.Query<int> (get_track_id_cmd, DbId, new SafeUri (uri).AbsoluteUri);
+        }
+
         private bool is_adding;
         public bool IsAdding {
             get { return is_adding; }
diff --git a/src/Core/Banshee.Services/Makefile.am b/src/Core/Banshee.Services/Makefile.am
index aa263da..b1bd49e 100644
--- a/src/Core/Banshee.Services/Makefile.am
+++ b/src/Core/Banshee.Services/Makefile.am
@@ -74,7 +74,6 @@ SOURCES =  \
 	Banshee.Library/IImportSource.cs \
 	Banshee.Library/ImportSourceManager.cs \
 	Banshee.Library/LibraryImportManager.cs \
-	Banshee.Library/LibraryLocationPreference.cs \
 	Banshee.Library/LibrarySource.cs \
 	Banshee.Library/MusicLibrarySource.cs \
 	Banshee.Library/ThreadPoolImportSource.cs \
diff --git a/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/TrackEditorDialog.cs b/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/TrackEditorDialog.cs
index aae4cc1..d0cba97 100644
--- a/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/TrackEditorDialog.cs
+++ b/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/TrackEditorDialog.cs
@@ -563,7 +563,7 @@ namespace Banshee.Gui.TrackEditor
 
         private void MoveSavedFile (TrackInfo track)
         {
-            Scheduler.Schedule (new MoveOnInfoSaveJob (track), JobPriority.Highest);
+            Scheduler.Schedule (new MoveOnInfoSaveJob (track as DatabaseTrackInfo), JobPriority.Highest);
         }
 
 #endregion
diff --git a/src/Core/Banshee.ThickClient/Banshee.Gui/GlobalActions.cs b/src/Core/Banshee.ThickClient/Banshee.Gui/GlobalActions.cs
index 6abb9e7..93354b6 100644
--- a/src/Core/Banshee.ThickClient/Banshee.Gui/GlobalActions.cs
+++ b/src/Core/Banshee.ThickClient/Banshee.Gui/GlobalActions.cs
@@ -168,9 +168,10 @@ namespace Banshee.Gui
             chooser.DefaultResponse = ResponseType.Ok;
             chooser.SelectMultiple = true;
             chooser.AddFilter (Hyena.Gui.GtkUtilities.GetFileFilter (Catalog.GetString ("Playlists"), PlaylistFileUtil.PlaylistExtensions));
-            try {
+            // TODO library-location add the BaseDirectory for the library being imported to (or all of them)
+            /*try {
                 chooser.AddShortcutFolder (Paths.LibraryLocation);
-            } catch {}
+            } catch {}*/
 
             chooser.AddButton (Stock.Cancel, ResponseType.Cancel);
             // Translators: verb
diff --git a/src/Core/Banshee.ThickClient/Banshee.Gui/SourceActions.cs b/src/Core/Banshee.ThickClient/Banshee.Gui/SourceActions.cs
index faa5759..ee8e49a 100644
--- a/src/Core/Banshee.ThickClient/Banshee.Gui/SourceActions.cs
+++ b/src/Core/Banshee.ThickClient/Banshee.Gui/SourceActions.cs
@@ -105,7 +105,7 @@ namespace Banshee.Gui
                     Catalog.GetString ("Sort Children by"), null, null,
                     OnSortChildrenMenu),
 
-                new ActionEntry ("SourcePreferencesAction", null, String.Empty, null, 
+                new ActionEntry ("SourcePreferencesAction", null, Catalog.GetString ("Preferences"), null, 
                     Catalog.GetString ("Edit preferences related to this source"), OnSourcePreferences),
 
             });
diff --git a/src/Core/Banshee.ThickClient/Banshee.Preferences.Gui/DefaultPreferenceWidgets.cs b/src/Core/Banshee.ThickClient/Banshee.Preferences.Gui/DefaultPreferenceWidgets.cs
index 932af9e..5bc5f3e 100644
--- a/src/Core/Banshee.ThickClient/Banshee.Preferences.Gui/DefaultPreferenceWidgets.cs
+++ b/src/Core/Banshee.ThickClient/Banshee.Preferences.Gui/DefaultPreferenceWidgets.cs
@@ -51,8 +51,9 @@ namespace Banshee.Preferences.Gui
         {
             Page music = ServiceManager.SourceManager.MusicLibrary.PreferencesPage;
         
-            PreferenceBase library_location = music["library-location"]["library-location"];
-            library_location.DisplayWidget = new LibraryLocationButton (library_location);
+            foreach (LibrarySource source in ServiceManager.SourceManager.FindSources<LibrarySource> ()) {
+                new LibraryLocationButton (source);
+            }
             
             PreferenceBase folder_pattern = music["file-system"]["folder_pattern"];
             folder_pattern.DisplayWidget = new PatternComboBox (folder_pattern, FileNamePattern.SuggestedFolders);
@@ -77,15 +78,20 @@ namespace Banshee.Preferences.Gui
 
         private class LibraryLocationButton : HBox
         {
+            private LibrarySource source;
+            private SchemaPreference<string> preference;
             private FileChooserButton chooser;
             private Button reset;
-            private LibraryLocationPreference preference;
             private string created_directory;
 
-            public LibraryLocationButton (PreferenceBase pref)
+            public LibraryLocationButton (LibrarySource source)
             {
-                preference = (LibraryLocationPreference)pref;
+                this.source = source;
+                preference = source.PreferencesPage["library-location"]["library-location"] as SchemaPreference<string>;
                 preference.ShowLabel = false;
+                preference.DisplayWidget = this;
+
+                string dir = preference.Value ?? source.DefaultBaseDirectory;
                 
                 Spacing = 5;
                 
@@ -93,9 +99,9 @@ namespace Banshee.Preferences.Gui
                 // so create it if it doesn't and store the fact that we did
                 // in case it ends up not being used, we can remove it
                 try {
-                    if (!Banshee.IO.Directory.Exists (preference.Value)) {
-                        Banshee.IO.Directory.Create (preference.Value);
-                        created_directory = preference.Value;
+                    if (!Banshee.IO.Directory.Exists (dir)) {
+                        Banshee.IO.Directory.Create (dir);
+                        created_directory = dir;
                         Log.DebugFormat ("Created library directory: {0}", created_directory);
                     } 
                 } catch {
@@ -103,7 +109,7 @@ namespace Banshee.Preferences.Gui
 
                 chooser = new FileChooserButton (Catalog.GetString ("Select library location"), 
                     FileChooserAction.SelectFolder);
-                chooser.SetCurrentFolder (preference.Value);
+                chooser.SetCurrentFolder (dir);
                 chooser.SelectionChanged += OnChooserChanged;
                     
                 HBox box = new HBox ();
@@ -113,9 +119,14 @@ namespace Banshee.Preferences.Gui
                 reset = new Button ();
                 reset.Clicked += OnReset;
                 reset.Add (box);
+
+                //Button open = new Button ();
+                //open.PackStart (new Image (Stock.Open, IconSize.Button), false, false, 0);
+                //open.Clicked += OnOpen;
                 
                 PackStart (chooser, true, true, 0);
                 PackStart (reset, false, false, 0);
+                //PackStart (open, false, false, 0);
                 
                 chooser.Show ();
                 reset.ShowAll ();
@@ -123,8 +134,13 @@ namespace Banshee.Preferences.Gui
             
             private void OnReset (object o, EventArgs args)
             {
-                chooser.SetFilename (Paths.DefaultLibraryPath);
+                chooser.SetFilename (source.DefaultBaseDirectory);
             }
+
+            //private void OnOpen (object o, EventArgs args)
+            //{
+                //open chooser.Filename
+            //}
             
             private void OnChooserChanged (object o, EventArgs args)
             {
@@ -139,7 +155,7 @@ namespace Banshee.Preferences.Gui
                     try {
                         Banshee.IO.Directory.Delete (created_directory);
                         if (!Banshee.IO.Directory.Exists (created_directory)) {
-                            Log.DebugFormat ("Deleted unusedi and empty previous library directory: {0}", created_directory);
+                            Log.DebugFormat ("Deleted unused and empty previous library directory: {0}", created_directory);
                             created_directory = null;
                         }
                     } catch {
diff --git a/src/Core/Banshee.ThickClient/Banshee.Preferences.Gui/NotebookPage.cs b/src/Core/Banshee.ThickClient/Banshee.Preferences.Gui/NotebookPage.cs
index ba8fd19..4e153b0 100644
--- a/src/Core/Banshee.ThickClient/Banshee.Preferences.Gui/NotebookPage.cs
+++ b/src/Core/Banshee.ThickClient/Banshee.Preferences.Gui/NotebookPage.cs
@@ -80,7 +80,6 @@ namespace Banshee.Preferences.Gui
                     foreach (Page child_page in page.ChildPages) {
                         NotebookPage page_ui = new NotebookPage (child_page);
                         page_ui.BorderWidth = 0;
-                        page_ui.Spacing = 0;
                         page_ui.Show ();
                         notebook.AppendPage (page_ui, null);
                     }
diff --git a/src/Core/Banshee.ThickClient/Banshee.Preferences.Gui/PageComboBox.cs b/src/Core/Banshee.ThickClient/Banshee.Preferences.Gui/PageComboBox.cs
index 9a90d1a..fb8c2c7 100644
--- a/src/Core/Banshee.ThickClient/Banshee.Preferences.Gui/PageComboBox.cs
+++ b/src/Core/Banshee.ThickClient/Banshee.Preferences.Gui/PageComboBox.cs
@@ -45,20 +45,25 @@ namespace Banshee.Preferences.Gui
             this.notebook = notebook;
 
             // icon, name, order, Page object itself
-            model = new ListStore (typeof(string), typeof(string), typeof(int), typeof(Page));
+            model = new ListStore (typeof(Gdk.Pixbuf), typeof(string), typeof(int), typeof(Page));
             model.SetSortColumnId (2, SortType.Ascending);
             Model = model;
 
             CellRendererPixbuf icon = new CellRendererPixbuf ();
             PackStart (icon, false);
-            AddAttribute (icon, "icon-name", 0);
+            AddAttribute (icon, "pixbuf", 0);
 
             CellRendererText name = new CellRendererText ();
             PackStart (name, true);
-            AddAttribute (name, "text", 1);
+            AddAttribute (name, "markup", 1);
 
             foreach (Page page in pages) {
-                model.AppendValues (page.IconName ?? "image-missing", page.Name, page.Order, page);
+                model.AppendValues (
+                    Banshee.Gui.IconThemeUtils.LoadIcon (page.IconName, 22),
+                    String.Format ("<b>{0}</b>", page.Name),
+                    page.Order,
+                    page
+                );
             }
 
             Active = 0;
diff --git a/src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/MassStorageSource.cs b/src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/MassStorageSource.cs
index 5a6d995..c16250c 100644
--- a/src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/MassStorageSource.cs
+++ b/src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/MassStorageSource.cs
@@ -165,7 +165,7 @@ namespace Banshee.Dap.MassStorage
                 //Hyena.Data.Sqlite.HyenaSqliteCommand.LogAll = true;
                 foreach (Dictionary<string, object> element in loaded_playlist.Elements) {
                     string track_path = (element["uri"] as Uri).LocalPath;
-                    int track_id = DatabaseTrackInfo.GetTrackIdForUri (track_path, Paths.MakePathRelative (track_path, BaseDirectory), psources);
+                    int track_id = DatabaseTrackInfo.GetTrackIdForUri (new SafeUri (track_path), psources);
                     if (track_id == 0) {
                         Log.DebugFormat ("Failed to find track {0} in DAP library to load it into playlist {1}", track_path, playlist_path);
                     } else {
diff --git a/src/Extensions/Banshee.AudioCd/Banshee.AudioCd/AudioCdRipper.cs b/src/Extensions/Banshee.AudioCd/Banshee.AudioCd/AudioCdRipper.cs
index 5612abc..3a2af96 100644
--- a/src/Extensions/Banshee.AudioCd/Banshee.AudioCd/AudioCdRipper.cs
+++ b/src/Extensions/Banshee.AudioCd/Banshee.AudioCd/AudioCdRipper.cs
@@ -181,7 +181,7 @@ namespace Banshee.AudioCd
             status = String.Format("{0} - {1}", track.ArtistName, track.TrackTitle);
             user_job.Status = status;
             
-            SafeUri uri = new SafeUri (FileNamePattern.BuildFull (track, null));
+            SafeUri uri = new SafeUri (FileNamePattern.BuildFull (ServiceManager.SourceManager.MusicLibrary.BaseDirectory, track, null));
             bool tagging_supported;
             ripper.RipTrack (track.IndexOnDisc, track, uri, out tagging_supported);
         }
diff --git a/src/Extensions/Banshee.Bpm/Banshee.Bpm/BpmDetectJob.cs b/src/Extensions/Banshee.Bpm/Banshee.Bpm/BpmDetectJob.cs
index a1d2305..b65ed85 100644
--- a/src/Extensions/Banshee.Bpm/Banshee.Bpm/BpmDetectJob.cs
+++ b/src/Extensions/Banshee.Bpm/Banshee.Bpm/BpmDetectJob.cs
@@ -70,7 +70,7 @@ namespace Banshee.Bpm
             ));
 
             SelectCommand = new HyenaSqliteCommand (String.Format (@"
-                SELECT DISTINCT Uri, UriType, TrackID
+                SELECT DISTINCT Uri, TrackID
                 FROM CoreTracks
                 WHERE PrimarySourceID IN ({0}) AND (BPM = 0 OR BPM IS NULL) LIMIT 1",
                 music_library.DbId
@@ -96,10 +96,8 @@ namespace Banshee.Bpm
 
         protected override void IterateCore (HyenaDataReader reader)
         {
-            SafeUri uri = music_library.UriAndTypeToSafeUri (
-                reader.Get<TrackUriType> (1), reader.Get<string> (0)
-            );
-            current_track_id = reader.Get<int> (2);
+            SafeUri uri = new SafeUri (reader.Get<string> (0));
+            current_track_id = reader.Get<int> (1);
             detector.ProcessFile (uri);
         }
 
diff --git a/src/Extensions/Banshee.CoverArt/Banshee.CoverArt/CoverArtJob.cs b/src/Extensions/Banshee.CoverArt/Banshee.CoverArt/CoverArtJob.cs
index b06aafd..b385b95 100644
--- a/src/Extensions/Banshee.CoverArt/Banshee.CoverArt/CoverArtJob.cs
+++ b/src/Extensions/Banshee.CoverArt/Banshee.CoverArt/CoverArtJob.cs
@@ -69,7 +69,7 @@ namespace Banshee.CoverArt
                         LastAttempt > ? OR Downloaded = 1)");
 
         private static HyenaSqliteCommand select_query = new HyenaSqliteCommand (@"
-            SELECT DISTINCT CoreAlbums.AlbumID, CoreAlbums.Title, CoreArtists.Name, CoreTracks.Uri, CoreTracks.UriType
+            SELECT DISTINCT CoreAlbums.AlbumID, CoreAlbums.Title, CoreArtists.Name, CoreTracks.Uri
             FROM CoreTracks, CoreArtists, CoreAlbums
             WHERE
                 CoreTracks.PrimarySourceID = ? AND
@@ -139,7 +139,7 @@ namespace Banshee.CoverArt
                             track.AlbumTitle = reader.Get<string> (1);
                             track.ArtistName = reader.Get<string> (2);
                             track.PrimarySource = ServiceManager.SourceManager.MusicLibrary;
-                            track.Uri = track.PrimarySource.UriAndTypeToSafeUri (reader.Get<TrackUriType> (4), reader.Get<string> (3));
+                            track.Uri = new SafeUri (reader.Get<string> (3));
                             track.AlbumId = reader.Get<int> (0);
                             //Console.WriteLine ("have album {0}/{1} for track uri {2}", track.AlbumId, track.AlbumTitle, track.Uri);
 
diff --git a/src/Extensions/Banshee.FileSystemQueue/Banshee.FileSystemQueue/FileSystemQueueSource.cs b/src/Extensions/Banshee.FileSystemQueue/Banshee.FileSystemQueue/FileSystemQueueSource.cs
index 4f3ab23..e81e6f7 100644
--- a/src/Extensions/Banshee.FileSystemQueue/Banshee.FileSystemQueue/FileSystemQueueSource.cs
+++ b/src/Extensions/Banshee.FileSystemQueue/Banshee.FileSystemQueue/FileSystemQueueSource.cs
@@ -184,10 +184,8 @@ namespace Banshee.FileSystemQueue
             if (uri == null) {
                 return;
             }
-            
-            int id = DatabaseTrackInfo.GetTrackIdForUri (uri, Paths.MakePathRelative (
-                uri.AbsolutePath, BaseDirectory), new int [] { DbId });
-            
+
+            int id = DatabaseTrackInfo.GetTrackIdForUri (uri, new int [] { DbId });
             if (id >= 0) {
                 int index = (int)TrackCache.IndexOf ((long)id);
                 if (index >= 0) {
diff --git a/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueSource.cs b/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueSource.cs
index 59f55bc..d2e1dc9 100644
--- a/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueSource.cs
+++ b/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueSource.cs
@@ -113,7 +113,7 @@ namespace Banshee.PlayQueue
 
         public void EnqueueUri (string uri, bool prepend)
         {
-            EnqueueId (LibrarySource.GetTrackIdForUri (uri), prepend);
+            EnqueueId (DatabaseTrackInfo.GetTrackIdForUri (uri), prepend);
         }
         
         public void EnqueueTrack (TrackInfo track, bool prepend)
diff --git a/src/Extensions/Banshee.PlayerMigration/Banshee.PlayerMigration/RhythmboxPlayerImportSource.cs b/src/Extensions/Banshee.PlayerMigration/Banshee.PlayerMigration/RhythmboxPlayerImportSource.cs
index 9058979..d4a1e4f 100644
--- a/src/Extensions/Banshee.PlayerMigration/Banshee.PlayerMigration/RhythmboxPlayerImportSource.cs
+++ b/src/Extensions/Banshee.PlayerMigration/Banshee.PlayerMigration/RhythmboxPlayerImportSource.cs
@@ -327,7 +327,7 @@ namespace Banshee.PlayerMigration
                             continue;
                         }
                         
-                        int track_id = Banshee.Library.LibrarySource.GetTrackIdForUri (entry.InnerText);
+                        int track_id = ServiceManager.SourceManager.MusicLibrary.GetTrackIdForUri (entry.InnerText);
                         if (track_id > 0) {
                             ServiceManager.DbConnection.Execute (insert_command, track_id);
                         }
diff --git a/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Data/PodcastSource.cs b/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Data/PodcastSource.cs
index d780284..b1e663b 100644
--- a/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Data/PodcastSource.cs
+++ b/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Data/PodcastSource.cs
@@ -57,10 +57,12 @@ namespace Banshee.Podcasting.Gui
     public class PodcastSource : Banshee.Library.LibrarySource
     {
         private PodcastFeedModel feed_model;
-
-        private string baseDirectory;
-        public override string BaseDirectory {
-            get { return baseDirectory; }
+        
+        public override string DefaultBaseDirectory {
+            get {
+                // HACK there isn't an XDG_PODCASTS_DIR; propose it?
+                return XdgBaseDirectorySpec.GetUserDirectory ("XDG_PODCASTS_DIR", "Podcasts");
+            }
         }
 
         public override bool CanRename {
@@ -82,17 +84,15 @@ namespace Banshee.Podcasting.Gui
         public PodcastFeedModel FeedModel {
             get { return feed_model; }
         }
-        
 
-#region Constructors
-
-        public PodcastSource () : this (null)
-        {
+        public override string PreferencesPageId {
+            get { return UniqueId; }
         }
 
-        public PodcastSource (string baseDirectory) : base (Catalog.GetString ("Podcasts"), "PodcastLibrary", 200)
+#region Constructors
+
+        public PodcastSource () : base (Catalog.GetString ("Podcasts"), "PodcastLibrary", 200)
         {
-            this.baseDirectory = baseDirectory;
             TrackExternalObjectHandler = GetPodcastInfoObject;
             TrackArtworkIdHandler = GetTrackArtworkId;
             MediaTypes = TrackMediaAttributes.Podcast;
diff --git a/src/Extensions/Banshee.Podcasting/Banshee.Podcasting/PodcastService.cs b/src/Extensions/Banshee.Podcasting/Banshee.Podcasting/PodcastService.cs
index e3a0961..2e64e2d 100644
--- a/src/Extensions/Banshee.Podcasting/Banshee.Podcasting/PodcastService.cs
+++ b/src/Extensions/Banshee.Podcasting/Banshee.Podcasting/PodcastService.cs
@@ -54,8 +54,7 @@ namespace Banshee.Podcasting
 {
     public partial class PodcastService : IExtensionService, IDisposable, IDelayedInitializeService
     {  
-        private readonly string tmp_download_path;
-        private string tmp_enclosure_path;
+        private readonly string tmp_download_path = Paths.Combine (Paths.ExtensionCacheRoot, "podcasting", "partial-downloads");
         private uint refresh_timeout_id = 0;
             
         private bool disposed;
@@ -72,19 +71,7 @@ namespace Banshee.Podcasting
 
         public PodcastService ()
         {
-            // TODO translate Podcasts folder?
-            // If changed, change HACK in src/Core/Banshee.Services/Banshee.Collection/RescanPipeline.cs too
-            tmp_enclosure_path = Path.Combine (Paths.LibraryLocation, "Podcasts");
-            tmp_download_path = Paths.Combine (Paths.ExtensionCacheRoot, "podcasting", "partial-downloads");
             Migo.Net.AsyncWebClient.DefaultUserAgent = Banshee.Web.Browser.UserAgent;
-            
-            download_manager = new DownloadManager (2, tmp_download_path);
-            download_manager_iface = new DownloadManagerInterface (download_manager);
-            download_manager_iface.Initialize ();    
-    
-            feeds_manager = new FeedsManager (ServiceManager.DbConnection, download_manager, Path.Combine (Banshee.Base.Paths.CachedLibraryLocation, "Podcasts"));
-
-            InitializeInterface ();
         }
 
         private void MigrateLegacyIfNeeded ()
@@ -143,10 +130,7 @@ namespace Banshee.Podcasting
                     int moved = 0;
                     foreach (FeedEnclosure enclosure in FeedEnclosure.Provider.FetchAllMatching ("LocalPath IS NOT NULL AND LocalPath != ''")) {
                         SafeUri uri = new SafeUri (enclosure.LocalPath);
-                        int track_id = DatabaseTrackInfo.GetTrackIdForUri (
-                            uri, Paths.MakePathRelative (uri.LocalPath, tmp_enclosure_path),
-                            primary_source_ids
-                        );
+                        int track_id = DatabaseTrackInfo.GetTrackIdForUri (uri, primary_source_ids);
 
                         if (track_id > 0) {
                             PodcastTrackInfo pi = new PodcastTrackInfo (DatabaseTrackInfo.Provider.FetchSingle (track_id));
@@ -231,6 +215,12 @@ namespace Banshee.Podcasting
         
         public void DelayedInitialize ()
         {
+            download_manager = new DownloadManager (2, tmp_download_path);
+            download_manager_iface = new DownloadManagerInterface (download_manager);
+            download_manager_iface.Initialize ();    
+            
+            feeds_manager = new FeedsManager (ServiceManager.DbConnection, download_manager, null);
+
             // Migrate data from 0.13.2 podcast tables, if they exist
             MigrateLegacyIfNeeded ();
 
@@ -240,12 +230,36 @@ namespace Banshee.Podcasting
             } catch (Exception e) {
                 Hyena.Log.Exception ("Couldn't migrate podcast download cache", e);
             }
-            
+
+            InitializeInterface ();
+            feeds_manager.PodcastStorageDirectory = source.BaseDirectory;
             feeds_manager.FeedManager.ItemAdded += OnItemAdded;
             feeds_manager.FeedManager.ItemChanged += OnItemChanged;
             feeds_manager.FeedManager.ItemRemoved += OnItemRemoved;
             feeds_manager.FeedManager.FeedsChanged += OnFeedsChanged;
 
+            if (DatabaseConfigurationClient.Client.Get<int> ("Podcast", "Version", 0) < 7) {
+                Banshee.Library.LibrarySource music_lib = ServiceManager.SourceManager.MusicLibrary;
+                if (music_lib != null) {
+                    string old_path = Path.Combine (music_lib.BaseDirectory, "Podcasts");
+                    string new_path = source.BaseDirectory;
+                    SafeUri old_uri = new SafeUri (old_path);
+                    SafeUri new_uri = new SafeUri (new_path);
+                    if (old_path != null && new_path != null && old_path != new_path &&
+                        Banshee.IO.Directory.Exists (old_path) && !Banshee.IO.Directory.Exists (new_path)) {
+                        Banshee.IO.Directory.Move (new SafeUri (old_path), new SafeUri (new_path));
+                        ServiceManager.DbConnection.Execute (String.Format (
+                            "UPDATE {0} SET LocalPath = REPLACE(LocalPath, ?, ?) WHERE LocalPath IS NOT NULL",
+                            FeedEnclosure.Provider.TableName), old_path, new_path);
+                        ServiceManager.DbConnection.Execute (
+                            "UPDATE CoreTracks SET Uri = REPLACE(Uri, ?, ?) WHERE Uri LIKE 'file://%' AND PrimarySourceId = ?",
+                            old_uri.AbsoluteUri, new_uri.AbsoluteUri, source.DbId);
+                        Hyena.Log.DebugFormat ("Moved Podcasts from {0} to {1}", old_path, new_path);
+                    }
+                }
+                DatabaseConfigurationClient.Client.Set<int> ("Podcast", "Version", 7);
+            }
+
             ServiceManager.PlayerEngine.ConnectEvent (OnPlayerEvent, PlayerEvent.StateChange);
             ServiceManager.Get<DBusCommandService> ().ArgumentPushed += OnCommandLineArgument;
 
diff --git a/src/Extensions/Banshee.Podcasting/Banshee.Podcasting/PodcastService_Interface.cs b/src/Extensions/Banshee.Podcasting/Banshee.Podcasting/PodcastService_Interface.cs
index 3ee5f1e..b54d588 100644
--- a/src/Extensions/Banshee.Podcasting/Banshee.Podcasting/PodcastService_Interface.cs
+++ b/src/Extensions/Banshee.Podcasting/Banshee.Podcasting/PodcastService_Interface.cs
@@ -55,13 +55,13 @@ namespace Banshee.Podcasting
 {
     public partial class PodcastService
     {                 
-        PodcastActions actions = null;
+        private PodcastActions actions = null;
          
         private void InitializeInterface ()
         {
-            source = new PodcastSource (tmp_enclosure_path);
-            ServiceManager.SourceManager.AddSource (source);
+            source = new PodcastSource ();
 
+            ServiceManager.SourceManager.AddSource (source);
             actions = new PodcastActions (source);
         }
         
diff --git a/src/Extensions/Banshee.Podcasting/Resources/GlobalUI.xml b/src/Extensions/Banshee.Podcasting/Resources/GlobalUI.xml
index 5d79b2a..8c27bbc 100644
--- a/src/Extensions/Banshee.Podcasting/Resources/GlobalUI.xml
+++ b/src/Extensions/Banshee.Podcasting/Resources/GlobalUI.xml
@@ -6,6 +6,8 @@
         <menuitem name="NewPlaylist" action="NewPlaylistAction"/>
         <menuitem name="NewSmartPlaylist" action="NewSmartPlaylistAction"/>
         <menu name="SortChildren" action="SortChildrenAction" />
+        <separator/>
+        <menuitem name="SourcePreferences" action="SourcePreferencesAction"/>
     </popup>
 
     <popup name="PodcastAllFeedsContextMenu" action="PodcastAllFeedsContextMenuAction">
diff --git a/src/Libraries/Migo/Migo.Syndication/FeedsManager.cs b/src/Libraries/Migo/Migo.Syndication/FeedsManager.cs
index e217838..78c0942 100644
--- a/src/Libraries/Migo/Migo.Syndication/FeedsManager.cs
+++ b/src/Libraries/Migo/Migo.Syndication/FeedsManager.cs
@@ -117,6 +117,7 @@ namespace Migo.Syndication
         private string podcast_base_dir;
         public string PodcastStorageDirectory {
             get { return podcast_base_dir; }
+            set { podcast_base_dir = value; }
         }
 
 #endregion



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