banshee r4463 - in trunk/banshee: . src/Backends/Banshee.Gnome/Banshee.GnomeBackend src/Clients/Nereid/Nereid src/Core/Banshee.Core/Banshee.Collection src/Core/Banshee.Core/Banshee.Streaming src/Core/Banshee.Services/Banshee.Collection.Database src/Core/Banshee.Services/Banshee.Database src/Core/Banshee.Services/Banshee.Library src/Core/Banshee.Services/Banshee.MediaProfiles src/Core/Banshee.Services/Banshee.Playlist src/Core/Banshee.Services/Banshee.Preferences src/Core/Banshee.Services/Banshee.SmartPlaylist src/Core/Banshee.Services/Banshee.Sources src/Core/Banshee.ThickClient src/Core/Banshee.ThickClient/Banshee.Gui src/Core/Banshee.ThickClient/Banshee.Gui.Widgets src/Core/Banshee.ThickClient/Banshee.Library.Gui src/Core/Banshee.ThickClient/Banshee.MediaProfiles.Gui src/Core/Banshee.ThickClient/Banshee.Preferences.Gui src/Core/Banshee.ThickClient/Banshee.Sources.Gui src/Dap/Banshee.Dap src/Dap/Banshee.Dap.Mtp src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp src/Dap/Banshee .Dap.Mtp/Banshee.Dap.Mtp/Tests src/Dap/Banshee.Dap/Banshee.Dap src/Dap/Banshee.Dap/Banshee.Dap.Gui src/Extensions/Banshee.AudioCd/Banshee.AudioCd src/Extensions/Banshee.CoverArt/Banshee.CoverArt src/Extensions/Banshee.Daap/Banshee.Daap src/Extensions/Banshee.FileSystemQueue/Banshee.FileSystemQueue src/Extensions/Banshee.InternetRadio/Banshee.InternetRadio src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Recommendations src/Extensions/Banshee.MiniMode/Banshee.MiniMode src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Data src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Gui src/Libraries/Hyena/Hyena.Data.Sqlite src/Libraries/Mtp/Mtp tests



Author: gburt
Date: Thu Sep  4 18:13:05 2008
New Revision: 4463
URL: http://svn.gnome.org/viewvc/banshee?rev=4463&view=rev

Log:
2008-09-04  Gabriel Burt  <gabriel burt gmail com>

	* src/Extensions/Banshee.CoverArt/Banshee.CoverArt/CoverArtService.cs:
	* src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Recommendations/RecommendationService.cs:
	* src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Gui/PodcastActions.cs:
	* src/Extensions/Banshee.MiniMode/Banshee.MiniMode/SourceModel.cs:
	* src/Extensions/Banshee.Daap/Banshee.Daap/DaapContainerSource.cs:
	* src/Extensions/Banshee.InternetRadio/Banshee.InternetRadio/InternetRadioSource.cs:
	* src/Extensions/Banshee.AudioCd/Banshee.AudioCd/AudioCdSource.cs:
	* src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueSource.cs:
	* src/Clients/Nereid/Nereid/PlayerInterface.cs:
	* src/Dap/Banshee.Dap/Banshee.Dap.Gui/DapContent.cs:
	* src/Dap/Banshee.Dap/Banshee.Dap.Gui/DapActions.cs:
	* src/Dap/Banshee.Dap/Banshee.Dap.Gui/DapInfoBar.cs:
	* src/Core/Banshee.ThickClient/Banshee.Gui/InterfaceActionService.cs:
	* src/Core/Banshee.ThickClient/Banshee.Gui/BansheeActionGroup.cs:
	* src/Core/Banshee.ThickClient/Banshee.Gui/SourceActions.cs:
	* src/Core/Banshee.ThickClient/Banshee.Gui/TrackActions.cs:
	* src/Core/Banshee.ThickClient/Banshee.Library.Gui/ImportDialog.cs:
	* src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/UserJobTileHost.cs:
	* src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/UserJobTile.cs:
	* src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceView.cs:
	* src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceModel.cs:
	* src/Core/Banshee.ThickClient/Banshee.Sources.Gui/FilteredListSourceContents.cs:
	* src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceComboBox.cs:
	* src/Backends/Banshee.Gnome/Banshee.GnomeBackend/Brasero.cs: Use
	ThreadAssist.ProxyToMain to ensure GUI actions happen on the main thread.

	* src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/StationSource.cs:
	* src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/LastfmSource.cs:
	* src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/NowPlayingSource.cs:
	* src/Extensions/Banshee.FileSystemQueue/Banshee.FileSystemQueue/FileSystemQueueSource.cs:
	Get rid of virtual TypeUniqueId property, replace with protected setter.

	* src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Data/PodcastSource.cs:
	Use the TypeUniqueId setter, and define SyncCondition and MediaType
	properties.

	* src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Data/PodcastTrackInfo.cs:
	Set the Podcast MediaType flag after loading the track info from file (if
	downloaded) to ensure it doesn't get unset.

	* src/Dap/Banshee.Dap.Mtp/Makefile.am:
	* src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp/Tests/MtpDapTests.cs: Tests for
	converting from TrackInfo to Mtp.Track and back.

	* tests/Makefile.am: Add Banshee.Dap.Mtp to list of assemblies to test.

	* src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp/MtpSource.cs: Be more careful
	about threading, add a GetFolderForTrack method to support Podcasts, and
	move the TrackInfo/Mtp.Track conversion into MtpTrackInfo.

	* src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp/MtpTrackInfo.cs: Try harder to
	set the MediaAttributes, and add an internal method for converting from
	TrackInfo to Mtp.Track.

	* src/Dap/Banshee.Dap/Makefile.am:
	* src/Dap/Banshee.Dap/Banshee.Dap/PodcastGroupSource.cs: New child of
	DAPs.

	* src/Dap/Banshee.Dap/Banshee.Dap/VideoGroupSource.cs:
	* src/Dap/Banshee.Dap/Banshee.Dap/MusicGroupSource.cs: Set the condition
	based on the Music/VideoLibrary's AttributesCondition.

	* src/Dap/Banshee.Dap/Banshee.Dap/DapSync.cs: Implement IDisposable, fix
	up preferences, listen for libraries to change and auto-sync if
	appropriate, move the to_remove list into each DapLibrarySync so they
	don't clobber other libraries' items.

	* src/Dap/Banshee.Dap/Banshee.Dap/DapSource.cs: Add PodcastGroupSource,
	use new TypeUniqueId setter, and auto-sync when plugged in if appropriate.

	* src/Dap/Banshee.Dap/Banshee.Dap/DapLibrarySync.cs: Add to_remove smart
	playlist, and actually implement deleting the tracks from the DAP and
	adding the new ones.

	* src/Core/Banshee.ThickClient/Banshee.Preferences.Gui/WidgetFactory.cs:
	If the ShowDescription property of the pref is true, then pack the widget
	into a VBox and put the description in a label below it.

	* src/Core/Banshee.ThickClient/Makefile.am:
	* src/Core/Banshee.ThickClient/Banshee.MediaProfiles.Gui/ProfileComboBoxConfigurable.cs:
	* src/Core/Banshee.ThickClient/Banshee.Preferences.Gui/DescriptionLabel.cs:
	New class that shows text formatted and can be updated via a delegate,
	factored out from code in ProfileComboBoxConfigurable.

	* src/Core/Banshee.Services/Banshee.MediaProfiles/MediaProfileManager.cs:
	Add new GetProfileForExtension helper method.

	* src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackInfo.cs:
	Lazily initialize the provider.

	* src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackListModel.cs:
	Prevent NRE and handle empty strings in the AddCondition method.

	* src/Core/Banshee.Services/Banshee.Preferences/Root.cs:
	* src/Core/Banshee.Services/Banshee.Preferences/Collection.cs: Override
	Sensitive and Visible setters, setting the value for each child.

	* src/Core/Banshee.Services/Banshee.Preferences/SchemaPreference.cs:
	* src/Core/Banshee.Services/Banshee.Preferences/Preference.cs: Raise
	ValueChanged event when the value is changed.

	* src/Core/Banshee.Services/Banshee.Preferences/Section.cs: Return the
	SchemaPreference<T> object created in the Add (SchemaEntry<T>) helper.

	* src/Core/Banshee.Services/Banshee.Preferences/PreferenceBase.cs: Add
	ShowDescription property, and ValueChanged event.

	* src/Core/Banshee.Services/Banshee.Playlist/PlaylistSource.cs:
	* src/Core/Banshee.Services/Banshee.Playlist/AbstractPlaylistSource.cs:
	* src/Core/Banshee.Services/Banshee.Sources/DatabaseSource.cs:
	* src/Core/Banshee.Services/Banshee.Sources/Source.cs: Use the new
	TypeUniqueId setter, and fix how DbId and AfterInitialize etc are called.

	* src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs: Add
	DeleteAllTracks method, refactor creation of expanded_schema, and
	ProxyToMain OnTracksAdded etc calls.

	* src/Core/Banshee.Services/Banshee.Sources/ErrorSource.cs: Use new
	TypeUniqueId setter and ProxyToMain for OnCleared and OnReloaded methods.

	* src/Core/Banshee.Services/Banshee.Database/BansheeDbFormatMigrator.cs:
	Set the Podcast MediaAttribute on all items in the Podcast primary source,
	since we had that bug in PodcastTrackInfo that's now fixed.

	* src/Core/Banshee.Services/Banshee.Library/LibraryLocationPreference.cs:
	Raise ValueChanged where appropriate.

	* src/Core/Banshee.Services/Banshee.Library/LibrarySource.cs: Add
	SyncCondition, AttributesCondition, MediaTypes, and NotMediaTypes
	properties.

	* src/Core/Banshee.Services/Banshee.Library/VideoLibrarySource.cs:
	* src/Core/Banshee.Services/Banshee.Library/MusicLibrarySource.cs: Set
	MediaTypes and NotMediaTypes to filter on audio/video/podcasts as
	appropriate.

	* src/Core/Banshee.Services/Banshee.SmartPlaylist/SmartPlaylistSource.cs:
	New AddCondition method for restricting a SmartPlaylist beyond the
	ConditionTree.

	* src/Core/Banshee.Core/Banshee.Collection/TrackInfo.cs: Rename IsMedia to
	HasAttribute, and add SetAttributeIf (bool, attr) helper.

	* src/Core/Banshee.Core/Banshee.Streaming/StreamTagger.cs: Only add new
	attributes in FindTrackMediaAttributes, don't remove current ones.

	* src/Backends/Banshee.Gnome/Banshee.GnomeBackend/GConfConfigurationClient.cs:
	Handle null keys.

	* src/Libraries/Mtp/Mtp/MtpDevice.cs: Make sure the folder is set, falling
	back to the MusicFolder if it's not.

	* src/Libraries/Mtp/Mtp/Track.cs: Add a Year helper property that sets the
	ReleaseDate appropriately, and add InFolder method.

	* src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteModelProvider.cs: Fix bug
	where VirtualColumns (values from tables other than the primary one)
	caused the join-condition with their table to be duplicated.

	* Makefile.am: Add make mdb helper, though I haven't really gotten it to
	work great yet.



Added:
   trunk/banshee/src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp/Tests/
   trunk/banshee/src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp/Tests/MtpDapTests.cs
Modified:
   trunk/banshee/ChangeLog
   trunk/banshee/Makefile.am
   trunk/banshee/src/Backends/Banshee.Gnome/Banshee.GnomeBackend/Brasero.cs
   trunk/banshee/src/Backends/Banshee.Gnome/Banshee.GnomeBackend/GConfConfigurationClient.cs
   trunk/banshee/src/Clients/Nereid/Nereid/PlayerInterface.cs
   trunk/banshee/src/Core/Banshee.Core/Banshee.Collection/TrackInfo.cs
   trunk/banshee/src/Core/Banshee.Core/Banshee.Streaming/StreamTagger.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackInfo.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackListModel.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Database/BansheeDbFormatMigrator.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Library/LibraryLocationPreference.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Library/LibrarySource.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Library/MusicLibrarySource.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Library/VideoLibrarySource.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.MediaProfiles/MediaProfileManager.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Playlist/AbstractPlaylistSource.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Playlist/PlaylistSource.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Preferences/Collection.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Preferences/Preference.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Preferences/PreferenceBase.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Preferences/Root.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Preferences/SchemaPreference.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Preferences/Section.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.SmartPlaylist/SmartPlaylistSource.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/DatabaseSource.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/ErrorSource.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/Source.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/UserJobTile.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/UserJobTileHost.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/BansheeActionGroup.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/InterfaceActionService.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/SourceActions.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/TrackActions.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Library.Gui/ImportDialog.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.MediaProfiles.Gui/ProfileComboBoxConfigurable.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Preferences.Gui/DescriptionLabel.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Preferences.Gui/WidgetFactory.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/FilteredListSourceContents.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceComboBox.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceModel.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceView.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Makefile.am
   trunk/banshee/src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp/MtpSource.cs
   trunk/banshee/src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp/MtpTrackInfo.cs
   trunk/banshee/src/Dap/Banshee.Dap.Mtp/Makefile.am
   trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap.Gui/DapActions.cs
   trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap.Gui/DapContent.cs
   trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap.Gui/DapInfoBar.cs
   trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap/DapLibrarySync.cs
   trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap/DapSource.cs
   trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap/DapSync.cs
   trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap/MusicGroupSource.cs
   trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap/PodcastGroupSource.cs
   trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap/VideoGroupSource.cs
   trunk/banshee/src/Dap/Banshee.Dap/Makefile.am
   trunk/banshee/src/Extensions/Banshee.AudioCd/Banshee.AudioCd/AudioCdSource.cs
   trunk/banshee/src/Extensions/Banshee.CoverArt/Banshee.CoverArt/CoverArtService.cs
   trunk/banshee/src/Extensions/Banshee.Daap/Banshee.Daap/DaapContainerSource.cs
   trunk/banshee/src/Extensions/Banshee.FileSystemQueue/Banshee.FileSystemQueue/FileSystemQueueSource.cs
   trunk/banshee/src/Extensions/Banshee.InternetRadio/Banshee.InternetRadio/InternetRadioSource.cs
   trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/LastfmSource.cs
   trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/StationSource.cs
   trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Recommendations/RecommendationService.cs
   trunk/banshee/src/Extensions/Banshee.MiniMode/Banshee.MiniMode/SourceModel.cs
   trunk/banshee/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/NowPlayingSource.cs
   trunk/banshee/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueSource.cs
   trunk/banshee/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Data/PodcastSource.cs
   trunk/banshee/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Data/PodcastTrackInfo.cs
   trunk/banshee/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Gui/PodcastActions.cs
   trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteModelProvider.cs
   trunk/banshee/src/Libraries/Mtp/Mtp/MtpDevice.cs
   trunk/banshee/src/Libraries/Mtp/Mtp/Track.cs
   trunk/banshee/tests/Makefile.am

Modified: trunk/banshee/Makefile.am
==============================================================================
--- trunk/banshee/Makefile.am	(original)
+++ trunk/banshee/Makefile.am	Thu Sep  4 18:13:05 2008
@@ -70,6 +70,11 @@
 	gdb mono --eval-command="handle SIGXCPU SIG35 SIGPWR nostop noprint" --eval-command="b g_return_if_fail_warning" --eval-command="r --debug Nereid.exe --debug --uninstalled"; \
 	popd;
 
+mdb:
+	@pushd bin; \
+	mdb -run -args Nereid.exe --debug --uninstalled"; \
+	popd;
+
 test:
 	@pushd tests; \
 	make test \

Modified: trunk/banshee/src/Backends/Banshee.Gnome/Banshee.GnomeBackend/Brasero.cs
==============================================================================
--- trunk/banshee/src/Backends/Banshee.Gnome/Banshee.GnomeBackend/Brasero.cs	(original)
+++ trunk/banshee/src/Backends/Banshee.Gnome/Banshee.GnomeBackend/Brasero.cs	Thu Sep  4 18:13:05 2008
@@ -72,8 +72,8 @@
             uia_service.UIManager.AddUiFromResource ("GlobalUI.xml");
             
             UpdateActions ();
-            uia_service.TrackActions.SelectionChanged += delegate { UpdateActions (); };
-            ServiceManager.SourceManager.ActiveSourceChanged += delegate { UpdateActions (); };
+            uia_service.TrackActions.SelectionChanged += delegate { Banshee.Base.ThreadAssist.ProxyToMain (UpdateActions); };
+            ServiceManager.SourceManager.ActiveSourceChanged += delegate { Banshee.Base.ThreadAssist.ProxyToMain (UpdateActions); };
         }
         
         public void Dispose ()

Modified: trunk/banshee/src/Backends/Banshee.Gnome/Banshee.GnomeBackend/GConfConfigurationClient.cs
==============================================================================
--- trunk/banshee/src/Backends/Banshee.Gnome/Banshee.GnomeBackend/GConfConfigurationClient.cs	(original)
+++ trunk/banshee/src/Backends/Banshee.Gnome/Banshee.GnomeBackend/GConfConfigurationClient.cs	Thu Sep  4 18:13:05 2008
@@ -93,7 +93,7 @@
         
         public T Get<T> (string @namespace, string key, T fallback)
         {
-            if (DisableGConf) {
+            if (DisableGConf || key == null) {
                 return fallback;
             }
             
@@ -120,7 +120,7 @@
         
         public void Set<T> (string @namespace, string key, T value)
         {
-            if (DisableGConf) {
+            if (DisableGConf || key == null) {
                 return;
             }
             

Modified: trunk/banshee/src/Clients/Nereid/Nereid/PlayerInterface.cs
==============================================================================
--- trunk/banshee/src/Clients/Nereid/Nereid/PlayerInterface.cs	(original)
+++ trunk/banshee/src/Clients/Nereid/Nereid/PlayerInterface.cs	Thu Sep  4 18:13:05 2008
@@ -316,7 +316,9 @@
         private void OnSourcePropertyChanged (object o, PropertyChangeEventArgs args)
         {
             if (args.PropertyName == "Nereid.SourceContents") {
-                UpdateSourceContents (previous_source);
+                Banshee.Base.ThreadAssist.ProxyToMain (delegate {
+                    UpdateSourceContents (previous_source);
+                });
             }
         }
         
@@ -377,8 +379,10 @@
         private void OnSourceUpdated (SourceEventArgs args)
         {
             if (args.Source == ServiceManager.SourceManager.ActiveSource) {
-                UpdateSourceInformation ();
-                view_container.Title = args.Source.Name;
+                Banshee.Base.ThreadAssist.ProxyToMain (delegate {
+                    UpdateSourceInformation ();
+                    view_container.Title = args.Source.Name;
+                });
             }
         }
 
@@ -482,7 +486,7 @@
 
         private void HandleTrackModelReloaded (object sender, EventArgs args)
         {
-            UpdateSourceInformation ();
+            Banshee.Base.ThreadAssist.ProxyToMain (UpdateSourceInformation);
         }
 
         private void UpdateSourceInformation ()

Modified: trunk/banshee/src/Core/Banshee.Core/Banshee.Collection/TrackInfo.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Core/Banshee.Collection/TrackInfo.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Core/Banshee.Collection/TrackInfo.cs	Thu Sep  4 18:13:05 2008
@@ -435,18 +435,25 @@
             set { media_attributes = value; }
         }
         
-        public bool IsMedia (TrackMediaAttributes attr)
+        public bool HasAttribute (TrackMediaAttributes attr)
         {
             return (MediaAttributes & attr) != 0;
         }
+
+        protected void SetAttributeIf (bool condition, TrackMediaAttributes attr)
+        {
+            if (condition) {
+                MediaAttributes |= attr;
+            }
+        }
         
         public string MediaTypeName {
             get {
-                if (IsMedia (TrackMediaAttributes.Podcast))
+                if (HasAttribute (TrackMediaAttributes.Podcast))
                     return Catalog.GetString ("Podcast");
-                if (IsMedia (TrackMediaAttributes.VideoStream))
+                if (HasAttribute (TrackMediaAttributes.VideoStream))
                     return Catalog.GetString ("Video");
-                if (IsMedia (TrackMediaAttributes.Music))
+                if (HasAttribute (TrackMediaAttributes.Music))
                     return Catalog.GetString ("Song");
                 return Catalog.GetString ("Item");
             }

Modified: trunk/banshee/src/Core/Banshee.Core/Banshee.Streaming/StreamTagger.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Core/Banshee.Streaming/StreamTagger.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Core/Banshee.Streaming/StreamTagger.cs	Thu Sep  4 18:13:05 2008
@@ -79,7 +79,7 @@
         
         private static void FindTrackMediaAttributes (TrackInfo track, TagLib.File file)
         {
-            track.MediaAttributes = TrackMediaAttributes.None;
+            track.MediaAttributes = track.MediaAttributes;
             
             if ((file.Properties.MediaTypes & TagLib.MediaTypes.Audio) != 0) {
                 track.MediaAttributes |= TrackMediaAttributes.AudioStream;

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackInfo.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackInfo.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackInfo.cs	Thu Sep  4 18:13:05 2008
@@ -60,12 +60,10 @@
 
     public class DatabaseTrackInfo : TrackInfo
     {
-        private static DatabaseTrackModelProvider<DatabaseTrackInfo> provider = new DatabaseTrackModelProvider<DatabaseTrackInfo> (
-            ServiceManager.DbConnection
-        );
+        private static DatabaseTrackModelProvider<DatabaseTrackInfo> provider;
 
         public static DatabaseTrackModelProvider<DatabaseTrackInfo> Provider {
-            get { return provider; }
+            get { return provider ?? provider = new DatabaseTrackModelProvider<DatabaseTrackInfo> (ServiceManager.DbConnection); }
         }
 
         private bool? artist_changed = null, album_changed = null;

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackListModel.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackListModel.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackListModel.cs	Thu Sep  4 18:13:05 2008
@@ -387,7 +387,9 @@
             set { 
                 forced_sort_query = value != null;
                 sort_query = value;
-                cache.Clear ();
+                if (cache != null) {
+                    cache.Clear ();
+                }
             }
         }
 
@@ -415,7 +417,9 @@
         
         public void AddCondition (string part)
         {
-            condition = condition == null ? part : String.Format ("{0} AND {1}", condition, part);
+            if (!String.IsNullOrEmpty (part)) {
+                condition = condition == null ? part : String.Format ("{0} AND {1}", condition, part);
+            }
         }
         
         public string Condition {

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Database/BansheeDbFormatMigrator.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Database/BansheeDbFormatMigrator.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Database/BansheeDbFormatMigrator.cs	Thu Sep  4 18:13:05 2008
@@ -52,7 +52,7 @@
         // 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 = 20;
+        protected const int CURRENT_VERSION = 21;
         protected const int CURRENT_METADATA_VERSION = 4;
         
 #region Migration Driver
@@ -522,6 +522,21 @@
         
 #endregion
 
+#region Version 21
+
+        [DatabaseVersion (21)]
+        private bool Migrate_21 ()
+        {
+            // We had a bug where downloaded podcast episodes would no longer have the Podcast attribute.
+            int id = connection.Query<int> ("SELECT PrimarySourceId FROM CorePrimarySources WHERE StringID = 'PodcastSource-PodcastLibrary'");
+            if (id > 0) {
+                connection.Execute ("UPDATE CoreTracks SET Attributes = Attributes | ? WHERE PrimarySourceID = ?", (int)TrackMediaAttributes.Podcast, id);
+            }
+            return true;
+        }
+        
+#endregion
+
 #pragma warning restore 0169
         
 #region Fresh database setup

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Library/LibraryLocationPreference.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Library/LibraryLocationPreference.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Library/LibraryLocationPreference.cs	Thu Sep  4 18:13:05 2008
@@ -42,7 +42,10 @@
         
         public override string Value {
             get { return Paths.LibraryLocation; }
-            set { Paths.LibraryLocation = value; }
+            set {
+                Paths.LibraryLocation = value;
+                OnValueChanged ();
+            }
         }
     }
 }

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Library/LibrarySource.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Library/LibrarySource.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Library/LibrarySource.cs	Thu Sep  4 18:13:05 2008
@@ -54,6 +54,28 @@
             AfterInitialized ();
         }
 
+        public string AttributesCondition {
+            get { return String.Format ("((CoreTracks.Attributes & {0}) == {0} AND (CoreTracks.Attributes & {1}) == 0)", (int)MediaTypes, (int)NotMediaTypes); }
+        }
+
+        private string sync_condition;
+        public string SyncCondition {
+            get { return sync_condition; }
+            protected set { sync_condition = value; }
+        }
+
+        private TrackMediaAttributes media_types;
+        protected TrackMediaAttributes MediaTypes {
+            get { return media_types; }
+            set { media_types = value; }
+        }
+
+        private TrackMediaAttributes not_media_types = TrackMediaAttributes.None;
+        protected TrackMediaAttributes NotMediaTypes {
+            get { return not_media_types; }
+            set { not_media_types = value; }
+        }
+
         public override string BaseDirectory {
             get { return Paths.CachedLibraryLocation; }
         }

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Library/MusicLibrarySource.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Library/MusicLibrarySource.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Library/MusicLibrarySource.cs	Thu Sep  4 18:13:05 2008
@@ -32,6 +32,7 @@
 
 using Mono.Unix;
 
+using Banshee.Collection;
 using Banshee.SmartPlaylist;
 
 namespace Banshee.Library
@@ -40,6 +41,8 @@
     {
         public MusicLibrarySource () : base (Catalog.GetString ("Music Library"), "Library", 40)
         {
+            MediaTypes = TrackMediaAttributes.Music | TrackMediaAttributes.AudioStream;
+            NotMediaTypes = TrackMediaAttributes.Podcast | TrackMediaAttributes.VideoStream | TrackMediaAttributes.AudioBook;
             Properties.SetStringList ("Icon.Name", "audio-x-generic", "source-library");
         }
 

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Library/VideoLibrarySource.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Library/VideoLibrarySource.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Library/VideoLibrarySource.cs	Thu Sep  4 18:13:05 2008
@@ -33,6 +33,7 @@
 using Mono.Unix;
 
 using Banshee.SmartPlaylist;
+using Banshee.Collection;
 
 namespace Banshee.Library
 {
@@ -40,6 +41,8 @@
     {
         public VideoLibrarySource () : base (Catalog.GetString ("Video Library"), "VideoLibrary", 50)
         {
+            MediaTypes = TrackMediaAttributes.VideoStream;
+            NotMediaTypes = TrackMediaAttributes.Podcast;
             Properties.SetStringList ("Icon.Name", "video-x-generic", "video", "source-library");
             Properties.SetString ("TrackView.ColumnControllerXml", String.Format (@"
                 <column-controller>

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.MediaProfiles/MediaProfileManager.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.MediaProfiles/MediaProfileManager.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.MediaProfiles/MediaProfileManager.cs	Thu Sep  4 18:13:05 2008
@@ -231,6 +231,22 @@
             return null;
         }
 
+        public Profile GetProfileForExtension (string extension)
+        {
+            if (extension == null || extension.Length < 2)
+                return null;
+
+            if (extension[0] == '.')
+                extension = extension.Substring (1, extension.Length - 1);
+            
+            foreach (Profile profile in this) {
+                if (profile.OutputFileExtension == extension) {
+                    return profile;
+                }
+            }
+            return null;
+        }
+
         public string GetExtensionForMimeType (string mimetype)
         {
             if (mimetype != null && mimetype_extensions.ContainsKey (mimetype))

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Playlist/AbstractPlaylistSource.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Playlist/AbstractPlaylistSource.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Playlist/AbstractPlaylistSource.cs	Thu Sep  4 18:13:05 2008
@@ -89,7 +89,6 @@
             protected set {
                 if (value != null && value != dbid) {
                     dbid = value;
-                    AfterInitialized ();
                 }
             }
         }
@@ -128,16 +127,20 @@
             }
         }
 
-        public AbstractPlaylistSource (string generic_name, string name, int primarySourceId)
-            : this (generic_name, name, null, -1, 0, primarySourceId, false)
+        public AbstractPlaylistSource (string generic_name, string name, int primarySourceId) : base ()
         {
+            GenericName = generic_name;
+            Name = name;
+            primary_source_id = primarySourceId;
         }
 
-        public AbstractPlaylistSource (string generic_name, string name, int? dbid, int sortColumn, int sortType, int primarySourceId, bool is_temp)
-            : base (generic_name, name, Convert.ToString (dbid), 500)
+        public AbstractPlaylistSource (string generic_name, string name, int dbid, int sortColumn, int sortType, int primarySourceId, bool is_temp)
+            : base (generic_name, name, dbid.ToString (), 500)
         {
+            DbId = dbid;
             IsTemporary = is_temp;
             this.primary_source_id = primarySourceId;
+            AfterInitialized ();
         }
 
         protected override void AfterInitialized ()
@@ -147,7 +150,6 @@
             DatabaseTrackModel.JoinColumn = "TrackID";
             DatabaseTrackModel.CachesJoinTableEntries = CachesJoinTableEntries;
             DatabaseTrackModel.AddCondition (String.Format (TrackCondition, dbid));
-
             base.AfterInitialized ();
         }
 
@@ -167,10 +169,14 @@
 
         public override void Save ()
         {
-            if (dbid == null || dbid <= 0)
+            if (dbid == null || dbid <= 0) {
                 Create ();
-            else
+                TypeUniqueId = dbid.ToString ();
+                Initialize ();
+                AfterInitialized ();
+            } else {
                 Update ();
+            }
         }
 
         // Have our parent handle deleting tracks

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Playlist/PlaylistSource.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Playlist/PlaylistSource.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Playlist/PlaylistSource.cs	Thu Sep  4 18:13:05 2008
@@ -107,26 +107,31 @@
 
 #region Constructors
 
-        public PlaylistSource (string name, int primarySourceId) : this (name, null, primarySourceId)
+        public PlaylistSource (string name, int primarySourceId) : base (generic_name, name, primarySourceId)
         {
+            SetProperties ();
         }
 
-        protected PlaylistSource (string name, int? dbid, int primarySourceId) : this (name, dbid, -1, 0, primarySourceId, 0, false)
+        protected PlaylistSource (string name, int dbid, int primarySourceId) : this (name, dbid, -1, 0, primarySourceId, 0, false)
         {
         }
 
-        protected PlaylistSource (string name, int? dbid, int sortColumn, int sortType, int primarySourceId, int count, bool is_temp)
+        protected PlaylistSource (string name, int dbid, int sortColumn, int sortType, int primarySourceId, int count, bool is_temp)
             : base (generic_name, name, dbid, sortColumn, sortType, primarySourceId, is_temp)
         {
-            Properties.SetString ("Icon.Name", "source-playlist");
-            Properties.SetString ("RemoveTracksActionLabel", Catalog.GetString ("Remove From Playlist"));
-            Properties.SetString ("UnmapSourceActionLabel", Catalog.GetString ("Delete Playlist"));
-            DbId = dbid;
+            SetProperties ();
             SavedCount = count;
         }
 
 #endregion
 
+        private void SetProperties ()
+        {
+            Properties.SetString ("Icon.Name", "source-playlist");
+            Properties.SetString ("RemoveTracksActionLabel", Catalog.GetString ("Remove From Playlist"));
+            Properties.SetString ("UnmapSourceActionLabel", Catalog.GetString ("Delete Playlist"));
+        }
+
 #region Source Overrides
 
         public override bool AcceptsInputFromSource (Source source)

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Preferences/Collection.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Preferences/Collection.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Preferences/Collection.cs	Thu Sep  4 18:13:05 2008
@@ -77,6 +77,30 @@
                 return null;
             }
         }
+
+#region Root overrides
+
+        public override bool Sensitive {
+            get { return base.Sensitive; }
+            set {
+                base.Sensitive = value;
+                foreach (Root child in this) {
+                    child.Sensitive = value;
+                }
+            }
+        }
+
+        public override bool Visible {
+            get { return base.Visible; }
+            set {
+                base.Visible = value;
+                foreach (Root child in this) {
+                    child.Visible = value;
+                }
+            }
+        }
+        
+#endregion
         
 #region IList
 

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Preferences/Preference.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Preferences/Preference.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Preferences/Preference.cs	Thu Sep  4 18:13:05 2008
@@ -52,7 +52,10 @@
         
         public virtual T Value {
             get { return this.value; }
-            set { this.value = value; }
+            set {
+                this.value = value;
+                OnValueChanged ();
+            }
         }
         
         public override object BoxedValue {

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Preferences/PreferenceBase.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Preferences/PreferenceBase.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Preferences/PreferenceBase.cs	Thu Sep  4 18:13:05 2008
@@ -31,7 +31,9 @@
 namespace Banshee.Preferences
 {
     public abstract class PreferenceBase : Root
-    {
+    {        
+        public event Action<Root> ValueChanged;
+
         public PreferenceBase ()
         {
         }
@@ -43,5 +45,19 @@
             get { return show_label; }
             set { show_label = value; }
         }
+
+        private bool show_description = false;
+        public virtual bool ShowDescription {
+            get { return show_description; }
+            set { show_description = value; }
+        }
+
+        protected void OnValueChanged ()
+        {
+            Action<Root> handler = ValueChanged;
+            if (handler != null) {
+                handler (this);
+            }
+        }
     }
 }

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Preferences/Root.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Preferences/Root.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Preferences/Root.cs	Thu Sep  4 18:13:05 2008
@@ -58,7 +58,7 @@
             
             return Order.CompareTo (r.Order);
         }
-        
+
         public string Id {
             get { return id; }
             set { id = value; }
@@ -79,7 +79,7 @@
             set { order = value; }
         }
         
-        public bool Sensitive {
+        public virtual bool Sensitive {
             get { return sensitive; }
             set {
                 sensitive = value;
@@ -87,7 +87,7 @@
             }
         }
         
-        public bool Visible {
+        public virtual bool Visible {
             get { return visible; }
             set {
                 visible = value;

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Preferences/SchemaPreference.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Preferences/SchemaPreference.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Preferences/SchemaPreference.cs	Thu Sep  4 18:13:05 2008
@@ -62,6 +62,7 @@
                 if (handler != null) {
                     handler ();
                 }
+                OnValueChanged ();
             }
         }
     }

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Preferences/Section.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Preferences/Section.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Preferences/Section.cs	Thu Sep  4 18:13:05 2008
@@ -40,7 +40,7 @@
             get { return show_label; }
             set { show_label = value; }
         }
-        
+
         public Section ()
         {
         }
@@ -52,9 +52,11 @@
             Order = order;
         }
 
-        public void Add<T> (SchemaEntry<T> schema)
+        public SchemaPreference<T> Add<T> (SchemaEntry<T> schema)
         {
-            Add (new SchemaPreference<T> (schema, schema.ShortDescription, schema.LongDescription));
+            SchemaPreference<T> pref = new SchemaPreference<T> (schema, schema.ShortDescription, schema.LongDescription);
+            Add (pref);
+            return pref;
         }
     }
 }

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.SmartPlaylist/SmartPlaylistSource.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.SmartPlaylist/SmartPlaylistSource.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.SmartPlaylist/SmartPlaylistSource.cs	Thu Sep  4 18:13:05 2008
@@ -125,6 +125,14 @@
             }
         }
 
+        private string additional_conditions;
+        public void AddCondition (string part)
+        {
+            if (!String.IsNullOrEmpty (part)) {
+                additional_conditions = additional_conditions == null ? part : String.Format ("{0} AND {1}", additional_conditions, part);
+            }
+        }
+
         private string condition_sql;
         public virtual string ConditionSql {
             get { return condition_sql; }
@@ -182,43 +190,39 @@
 
 #region Constructors
 
-        public SmartPlaylistSource (string name, int primarySourceId) : this (null, name, String.Empty, String.Empty, String.Empty, String.Empty, primarySourceId, 0, false)
+        public SmartPlaylistSource (string name, int primarySourceId) : base (generic_name, name, primarySourceId)
         {
+            SetProperties ();
         }
 
         public SmartPlaylistSource (string name, QueryNode condition, QueryOrder order, QueryLimit limit, IntegerQueryValue limit_value, int primarySourceId)
-            : base (generic_name, name, null, -1, 0, primarySourceId, false)
+            : this (name, primarySourceId)
         {
             ConditionTree = condition;
             QueryOrder = order;
             Limit = limit;
             LimitValue = limit_value;
 
-            InstallProperties ();
+            SetProperties ();
             UpdateDependencies ();
         }
 
         // For existing smart playlists that we're loading from the database
-        protected SmartPlaylistSource (int? dbid, string name, string condition_xml, string order_by, string limit_number, string limit_criterion, int primarySourceId, int count, bool is_temp) :
+        protected SmartPlaylistSource (int dbid, string name, string condition_xml, string order_by, string limit_number, string limit_criterion, int primarySourceId, int count, bool is_temp) :
             base (generic_name, name, dbid, -1, 0, primarySourceId, is_temp)
         {
             ConditionXml = condition_xml;
             QueryOrder = BansheeQuery.FindOrder (order_by);
-            
             Limit = BansheeQuery.FindLimit (limit_criterion);
-
             LimitValue = new IntegerQueryValue ();
             LimitValue.ParseUserQuery (limit_number);
-
-            DbId = dbid;
             SavedCount = count;
 
-            InstallProperties ();
-
+            SetProperties ();
             UpdateDependencies ();
         }
 
-        protected void InstallProperties ()
+        private void SetProperties ()
         {
             Properties.SetString ("Icon.Name", "source-smart-playlist");
             Properties.SetString ("SourcePropertiesActionLabel", properties_label);
@@ -346,11 +350,11 @@
             string reload_str = String.Format (
                 @"DELETE FROM CoreSmartPlaylistEntries WHERE SmartPlaylistID = {0};
                   INSERT INTO CoreSmartPlaylistEntries 
-                    SELECT NULL, {0} as SmartPlaylistID, TrackId
-                        FROM CoreTracks, CoreArtists, CoreAlbums
-                        WHERE CoreTracks.ArtistID = CoreArtists.ArtistID AND CoreTracks.AlbumID = CoreAlbums.AlbumID AND CoreTracks.PrimarySourceID = {1}
-                        {2} {3} {4}",
-                DbId, PrimarySourceId, PrependCondition("AND"), OrderSql, LimitSql
+                    SELECT NULL, {0} as SmartPlaylistID, TrackId FROM {1}
+                        WHERE {2} AND CoreTracks.PrimarySourceID = {3}
+                        {4} {5} {6}",
+                DbId, DatabaseTrackInfo.Provider.From, DatabaseTrackInfo.Provider.Where,
+                PrimarySourceId, PrependCondition ("AND"), OrderSql, LimitSql
             );
             ServiceManager.DbConnection.Execute (reload_str);
 
@@ -475,7 +479,11 @@
 
         private string PrependCondition (string with)
         {
-            return String.IsNullOrEmpty (ConditionSql) ? " " : String.Format ("{0} ({1})", with, ConditionSql);
+            string sql = String.IsNullOrEmpty (ConditionSql) ? " " : String.Format ("{0} ({1})", with, ConditionSql);
+            if (!String.IsNullOrEmpty (additional_conditions)) {
+                sql = String.IsNullOrEmpty (sql) ? additional_conditions : String.Format ("{0} AND ({1})", sql, additional_conditions);
+            }
+            return sql;
         }
 
         public static IEnumerable<SmartPlaylistSource> LoadAll (int primary_id)

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/DatabaseSource.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/DatabaseSource.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/DatabaseSource.cs	Thu Sep  4 18:13:05 2008
@@ -68,16 +68,10 @@
             }
         }
 
-        protected RateLimiter reload_limiter;
+        private RateLimiter reload_limiter;
         
-        protected string type_unique_id;
-        protected override string TypeUniqueId {
-            get { return type_unique_id; }
-        }
-        
-        public DatabaseSource (string generic_name, string name, string id, int order) : base (generic_name, name, order)
+        public DatabaseSource (string generic_name, string name, string id, int order) : base (generic_name, name, order, id)
         {
-            type_unique_id = id;
             DatabaseSourceInitialize ();
         }
 

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/ErrorSource.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/ErrorSource.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/ErrorSource.cs	Thu Sep  4 18:13:05 2008
@@ -44,12 +44,6 @@
         public event EventHandler Cleared;
         public event EventHandler Reloaded;
         
-        private static Random rand = new Random ();
-        private string tuid = rand.Next ().ToString ();
-        protected override string TypeUniqueId {
-            get { return tuid; }
-        }
-
         public ErrorSource (string name) : base (name, name, 0)
         {
             Properties.SetStringList ("Icon.Name", "dialog-error", "gtk-dialog-error");
@@ -66,18 +60,22 @@
         
         private void OnReloaded ()
         {
-            EventHandler handler = Reloaded;
-            if (handler != null) {
-                handler (this, EventArgs.Empty);
-            }
+            Banshee.Base.ThreadAssist.ProxyToMain (delegate {
+                EventHandler handler = Reloaded;
+                if (handler != null) {
+                    handler (this, EventArgs.Empty);
+                }
+            });
         }
         
         private void OnCleared ()
         {
-            EventHandler handler = Cleared;
-            if (handler != null) {
-                handler (this, EventArgs.Empty);
-            }
+            Banshee.Base.ThreadAssist.ProxyToMain (delegate {
+                EventHandler handler = Cleared;
+                if (handler != null) {
+                    handler (this, EventArgs.Empty);
+                }
+            });
         }
         
         private ColumnDescription [] columns = new ColumnDescription [] {

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs	Thu Sep  4 18:13:05 2008
@@ -102,7 +102,10 @@
             DELETE FROM CoreTracks WHERE PrimarySourceId = ?
         ");
 
-        public readonly SchemaEntry<bool> ExpandedSchema;
+        private SchemaEntry<bool> expanded_schema;
+        public SchemaEntry<bool> ExpandedSchema {
+            get { return expanded_schema; }
+        }
 
         private int dbid;
         public int DbId {
@@ -198,17 +201,10 @@
         protected PrimarySource (string generic_name, string name, string id, int order) : base (generic_name, name, id, order)
         {
             PrimarySourceInitialize ();
-
-            ExpandedSchema = new SchemaEntry<bool> (
-                String.Format ("sources.{0}", ConfigurationId), "expanded", true, "Is source expanded", "Is source expanded"
-            );
         }
 
         protected PrimarySource () : base ()
         {
-            ExpandedSchema = new SchemaEntry<bool> (
-                String.Format ("sources.{0}", ConfigurationId), "expanded", true, "Is source expanded", "Is source expanded"
-            );
         }
 
         public override bool? AutoExpand {
@@ -220,7 +216,6 @@
             set { ExpandedSchema.Set (value); }
         }
 
-
         public virtual void Dispose ()
         {
             if (Application.ShuttingDown)
@@ -276,6 +271,10 @@
                 // if we didn't have any and the list of default ones is empty atm).
                 if (sp_count > 0)
                     HaveCreatedSmartPlaylists = true;
+
+                expanded_schema = new SchemaEntry<bool> (
+                    String.Format ("sources.{0}", ConfigurationId), "expanded", true, "Is source expanded", "Is source expanded"
+                );
             }
         }
 
@@ -433,20 +432,28 @@
             DeleteSelectedTracks (source.TrackModel as DatabaseTrackListModel);
         }
 
-        protected override void DeleteSelectedTracks (DatabaseTrackListModel model)
+        public void DeleteAllTracks (AbstractPlaylistSource source)
         {
+            if (source.PrimarySource != this) {
+                Log.WarningFormat ("Cannot delete all tracks from {0} via primary source {1}", source, this);
+                return;
+            }
+            
             ThreadAssist.SpawnFromMain (delegate {
-                if (model == null)
-                    return;
+                CachedList<DatabaseTrackInfo> list = CachedList<DatabaseTrackInfo>.CreateFromModel (source.DatabaseTrackModel);
+                DeleteTrackList (list);
+            });
+        }
 
+        protected override void DeleteSelectedTracks (DatabaseTrackListModel model)
+        {
+            if (model == null) {
+                return;
+            }
+            
+            ThreadAssist.SpawnFromMain (delegate {
                 CachedList<DatabaseTrackInfo> list = CachedList<DatabaseTrackInfo>.CreateFromModelSelection (model);
                 DeleteTrackList (list);
-
-                OnTracksDeleted ();
-                OnUserNotifyUpdated ();
-                ThreadAssist.ProxyToMain (delegate {
-                    OnUpdated ();
-                });
             });
         }
 
@@ -485,6 +492,12 @@
 
             // Remove from database
             ServiceManager.DbConnection.Execute (remove_list_command, DateTime.Now, list.CacheId, list.CacheId);
+
+            ThreadAssist.ProxyToMain (delegate {
+                OnTracksDeleted ();
+                OnUserNotifyUpdated ();
+                OnUpdated ();
+            });
         }
 
         protected virtual void DeleteTrack (DatabaseTrackInfo track)
@@ -508,7 +521,11 @@
 
             // Store a snapshot of the current selection
             CachedList<DatabaseTrackInfo> cached_list = CachedList<DatabaseTrackInfo>.CreateFromModelSelection (model);
-            System.Threading.ThreadPool.QueueUserWorkItem (AddTrackList, cached_list);
+            if (ThreadAssist.InMainThread) {
+                System.Threading.ThreadPool.QueueUserWorkItem (AddTrackList, cached_list);
+            } else {
+                AddTrackList (cached_list);
+            }
             return true;
         }
         
@@ -519,7 +536,11 @@
             
             DatabaseTrackListModel model = (source as ITrackModelSource).TrackModel as DatabaseTrackListModel;
             CachedList<DatabaseTrackInfo> cached_list = CachedList<DatabaseTrackInfo>.CreateFromModel (model);
-            System.Threading.ThreadPool.QueueUserWorkItem (AddTrackList, cached_list);
+            if (ThreadAssist.InMainThread) {
+                System.Threading.ThreadPool.QueueUserWorkItem (AddTrackList, cached_list);
+            } else {
+                AddTrackList (cached_list);
+            }
             return true;
         }
 
@@ -587,11 +608,14 @@
                 }
             }
 
-            if (notify || finished)
-                OnTracksAdded ();
-
-            if (finished)
-                OnUserNotifyUpdated ();
+            if (notify || finished) {
+                Banshee.Base.ThreadAssist.ProxyToMain (delegate {
+                    OnTracksAdded ();
+    
+                if (finished)
+                    OnUserNotifyUpdated ();
+                });
+            }
         }
 
         private bool delay_add_job = true;

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/Source.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/Source.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/Source.cs	Thu Sep  4 18:13:05 2008
@@ -62,12 +62,17 @@
         public event SourceEventHandler ChildSourceRemoved;
 
         public delegate void OpenPropertiesDelegate ();
-        
-        protected Source (string generic_name, string name, int order)
+
+        protected Source (string generic_name, string name, int order) : this (generic_name, name, order, null)
+        {
+        }
+
+        protected Source (string generic_name, string name, int order, string type_unique_id)
         {
             GenericName = generic_name;
             Name = name;
             Order = order;
+            TypeUniqueId = type_unique_id;
 
             SourceInitialize ();
         }
@@ -165,32 +170,36 @@
         
         public virtual void AddChildSource (Source child)
         {
-            lock (Children) {
-                if (!child_sources.Contains (child)) {
-                    child.SetParentSource (this);
-                    child_sources.Add (child);
-                    OnChildSourceAdded (child);
+            ThreadAssist.ProxyToMain (delegate {
+                lock (Children) {
+                    if (!child_sources.Contains (child)) {
+                        child.SetParentSource (this);
+                        child_sources.Add (child);
+                        OnChildSourceAdded (child);
+                    }
                 }
-            }
+            });
         }
 
         public virtual void RemoveChildSource (Source child)
         {
-            lock (Children) {
-                if (child.Children.Count > 0) {
-                    child.ClearChildSources ();
-                }
-                
-                child_sources.Remove (child);
-                
-                if (ServiceManager.SourceManager.ActiveSource == child) {
-                    if (CanActivate) {
-                        ServiceManager.SourceManager.SetActiveSource (this);
+            ThreadAssist.ProxyToMain (delegate {
+                lock (Children) {
+                    if (child.Children.Count > 0) {
+                        child.ClearChildSources ();
+                    }
+                    
+                    child_sources.Remove (child);
+                    
+                    if (ServiceManager.SourceManager.ActiveSource == child) {
+                        if (CanActivate) {
+                            ServiceManager.SourceManager.SetActiveSource (this);
+                        }
                     }
+                    
+                    OnChildSourceRemoved (child);
                 }
-                
-                OnChildSourceRemoved (child);
-            }
+            });
         }
         
         public virtual void ClearChildSources ()
@@ -455,10 +464,19 @@
         
         private string unique_id;
         public string UniqueId {
-            get { return unique_id ?? unique_id = String.Format ("{0}-{1}", this.GetType ().Name, TypeUniqueId); }
+            get {
+                if (unique_id == null && type_unique_id == null) {
+                    Log.ErrorFormat ("Creating Source.UniqueId for {0}, but TypeUniqueId is null; trace is {1}", this.Name, System.Environment.StackTrace);
+                }
+                return unique_id ?? unique_id = String.Format ("{0}-{1}", this.GetType ().Name, TypeUniqueId);
+            }
         }
         
-        protected abstract string TypeUniqueId { get; }
+        private string type_unique_id;
+        protected string TypeUniqueId {
+            get { return type_unique_id; }
+            set { type_unique_id = value; }
+        }
 
         public virtual bool CanRename {
             get { return false; }

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/UserJobTile.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/UserJobTile.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/UserJobTile.cs	Thu Sep  4 18:13:05 2008
@@ -67,6 +67,7 @@
         
         private void BuildWidget ()
         {
+            ThreadAssist.AssertInMainThread ();
             ColumnSpacing = 5;
             RowSpacing = 2;
             
@@ -171,6 +172,7 @@
         
         private void UpdateFromJob ()
         {
+            ThreadAssist.AssertInMainThread ();
             if (cancel_dialog != null && !job.CanCancel) {
                 cancel_dialog.Respond (Gtk.ResponseType.Cancel);
             }

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/UserJobTileHost.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/UserJobTileHost.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/UserJobTileHost.cs	Thu Sep  4 18:13:05 2008
@@ -45,6 +45,7 @@
         
         public UserJobTileHost () : base (0.0f, 0.0f, 1.0f, 1.0f)
         {
+            Banshee.Base.ThreadAssist.AssertInMainThread ();
             LeftPadding = 4;
             
             box = new AnimatedVBox ();
@@ -77,6 +78,7 @@
                 }
                 
                 if ((job.DelayShow && job.Progress < 0.33) || !job.DelayShow) {
+                    Banshee.Base.ThreadAssist.AssertInMainThread ();
                     UserJobTile tile = new UserJobTile (job);
                     job_tiles.Add (job, tile);
                     job_start_times.Add (job, DateTime.Now);
@@ -105,6 +107,7 @@
         {
             lock (this) {
                 if (job_tiles.ContainsKey (job)) {
+                    Banshee.Base.ThreadAssist.AssertInMainThread ();
                     UserJobTile tile = job_tiles[job];
                     box.Remove (tile);
                     job_tiles.Remove (job);

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/BansheeActionGroup.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/BansheeActionGroup.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/BansheeActionGroup.cs	Thu Sep  4 18:13:05 2008
@@ -62,6 +62,7 @@
 
         public void AddUiFromFile (string ui_file)
         {
+            Banshee.Base.ThreadAssist.AssertInMainThread ();
             ui_merge_ids.Add (Actions.AddUiFromFile (ui_file, System.Reflection.Assembly.GetCallingAssembly ()));
         }
 
@@ -77,16 +78,18 @@
 
         public override void Dispose ()
         {
-            UnRegister ();
+            Banshee.Base.ThreadAssist.ProxyToMain (delegate {
+                UnRegister ();
 
-            foreach (uint merge_id in ui_merge_ids) {
-                if (merge_id > 0) {
-                    Actions.UIManager.RemoveUi (merge_id);
+                foreach (uint merge_id in ui_merge_ids) {
+                    if (merge_id > 0) {
+                        Actions.UIManager.RemoveUi (merge_id);
+                    }
                 }
-            }
-            ui_merge_ids.Clear ();
+                ui_merge_ids.Clear ();
 
-            base.Dispose ();
+                base.Dispose ();
+            });
         }
 
         public new void Add (ActionEntry [] action_entries)

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/InterfaceActionService.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/InterfaceActionService.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/InterfaceActionService.cs	Thu Sep  4 18:13:05 2008
@@ -166,31 +166,33 @@
         
         private void OnActiveSourceChanged (SourceEventArgs args)
         {
-            if (active_source_uiid > 0) {
-                ui_manager.RemoveUi (active_source_uiid);
-                active_source_uiid = 0;
-            }
+            Banshee.Base.ThreadAssist.ProxyToMain (delegate {
+                if (active_source_uiid > 0) {
+                    ui_manager.RemoveUi (active_source_uiid);
+                    active_source_uiid = 0;
+                }
+                    
+                if (active_source_actions != null) {
+                    RemoveActionGroup (active_source_actions.Name);
+                    active_source_actions = null;
+                }
                 
-            if (active_source_actions != null) {
-                RemoveActionGroup (active_source_actions.Name);
-                active_source_actions = null;
-            }
-            
-            Source active_source = ServiceManager.SourceManager.ActiveSource;
-            if (active_source == null) {
-                return;
-            }
-            
-            active_source_actions = active_source.Properties.Get<BansheeActionGroup> ("ActiveSourceActions");
-            if (active_source_actions != null) {
-                AddActionGroup (active_source_actions);
-            }
+                Source active_source = ServiceManager.SourceManager.ActiveSource;
+                if (active_source == null) {
+                    return;
+                }
                 
-            Assembly assembly = 
-                active_source.Properties.Get<Assembly> ("ActiveSourceUIResource.Assembly") ??
-                Assembly.GetAssembly (active_source.GetType ());
-
-            active_source_uiid = AddUiFromFile (active_source.Properties.Get<string> ("ActiveSourceUIResource"), assembly);
+                active_source_actions = active_source.Properties.Get<BansheeActionGroup> ("ActiveSourceActions");
+                if (active_source_actions != null) {
+                    AddActionGroup (active_source_actions);
+                }
+                    
+                Assembly assembly = 
+                    active_source.Properties.Get<Assembly> ("ActiveSourceUIResource.Assembly") ??
+                    Assembly.GetAssembly (active_source.GetType ());
+    
+                active_source_uiid = AddUiFromFile (active_source.Properties.Get<string> ("ActiveSourceUIResource"), assembly);
+            });
         }
 
         public uint AddUiFromFileInCurrentAssembly (string ui_file)

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/SourceActions.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/SourceActions.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/SourceActions.cs	Thu Sep  4 18:13:05 2008
@@ -143,15 +143,17 @@
 
         private void HandleActiveSourceChanged (SourceEventArgs args)
         {
-            UpdateActions ();
-            
-            if (last_source != null) {
-                last_source.Updated -= HandleActiveSourceUpdated;
-            }
-            
-            if (ActiveSource != null) {
-                ActiveSource.Updated += HandleActiveSourceUpdated;
-            }
+            Banshee.Base.ThreadAssist.ProxyToMain (delegate {
+                UpdateActions ();
+                
+                if (last_source != null) {
+                    last_source.Updated -= HandleActiveSourceUpdated;
+                }
+                
+                if (ActiveSource != null) {
+                    ActiveSource.Updated += HandleActiveSourceUpdated;
+                }
+            });
         }
 
         private void HandleEditMenuActivated (object sender, EventArgs args)
@@ -161,7 +163,9 @@
         
         private void HandleActiveSourceUpdated (object o, EventArgs args)
         {
-            UpdateActions (true);
+            Banshee.Base.ThreadAssist.ProxyToMain (delegate {
+                UpdateActions (true);
+            });
         }
 
 #endregion

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/TrackActions.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/TrackActions.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/TrackActions.cs	Thu Sep  4 18:13:05 2008
@@ -137,7 +137,7 @@
                 current_source = new_source;
             }
             
-            UpdateActions ();
+            Banshee.Base.ThreadAssist.ProxyToMain (UpdateActions);
         }
 
         private void HandleActionsChanged (object sender, EventArgs args)
@@ -152,8 +152,10 @@
 
         private void HandleSelectionChanged (object sender, EventArgs args)
         {
-            OnSelectionChanged ();
-            UpdateActions ();
+            Banshee.Base.ThreadAssist.ProxyToMain (delegate {
+                OnSelectionChanged ();
+                UpdateActions ();
+            });
         }
 
         private void HandleEditMenuActivated (object sender, EventArgs args)

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Library.Gui/ImportDialog.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Library.Gui/ImportDialog.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Library.Gui/ImportDialog.cs	Thu Sep  4 18:13:05 2008
@@ -159,27 +159,33 @@
         private void OnSourceAdded (SourceAddedArgs args)
         {
             if(args.Source is IImportSource) {
-                AddSource ((IImportSource)args.Source);
+                Banshee.Base.ThreadAssist.ProxyToMain (delegate {
+                    AddSource ((IImportSource)args.Source);
+                });
             }
         }
         
         private void OnSourceRemoved (SourceEventArgs args)
         {
             if (args.Source is IImportSource) {
-                TreeIter iter;
-                if (FindSourceIter (out iter, (IImportSource)args.Source)) {
-                    source_model.Remove (ref iter);
-                }
+                Banshee.Base.ThreadAssist.ProxyToMain (delegate {
+                    TreeIter iter;
+                    if (FindSourceIter (out iter, (IImportSource)args.Source)) {
+                        source_model.Remove (ref iter);
+                    }
+                });
             }
         }
         
         private void OnSourceUpdated (SourceEventArgs args)
         {
             if (args.Source is IImportSource) {
-                TreeIter iter;
-                if(FindSourceIter (out iter, (IImportSource)args.Source)) {
-                    source_model.SetValue (iter, 1, args.Source.Name);
-                }
+                Banshee.Base.ThreadAssist.ProxyToMain (delegate {
+                    TreeIter iter;
+                    if(FindSourceIter (out iter, (IImportSource)args.Source)) {
+                        source_model.SetValue (iter, 1, args.Source.Name);
+                    }
+                });
             }
         }
         

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.MediaProfiles.Gui/ProfileComboBoxConfigurable.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.MediaProfiles.Gui/ProfileComboBoxConfigurable.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.MediaProfiles.Gui/ProfileComboBoxConfigurable.cs	Thu Sep  4 18:13:05 2008
@@ -30,6 +30,7 @@
 using Gtk;
 
 using Hyena.Widgets;
+using Banshee.Preferences.Gui;
 
 namespace Banshee.MediaProfiles.Gui
 {
@@ -37,7 +38,7 @@
     {
         private ProfileComboBox combo;
         private ProfileConfigureButton button;
-        private WrapLabel description;
+        private DescriptionLabel description;
         private string configuration_id;
         
         public ProfileComboBoxConfigurable(MediaProfileManager manager, string configurationId) 
@@ -62,40 +63,24 @@
             editor.PackStart(button, false, false, 0);
             editor.Show();
             
-            description = new WrapLabel();
-            description.Show();
-            
             ProfileConfiguration config = manager.GetActiveProfileConfiguration (configurationId);
             
             if (config != null) {
                 Combo.SetActiveProfile(config.Profile);
             }
 
-            SetDescription();
+            description = new DescriptionLabel (delegate { return Combo.ActiveProfile.Description; });
             
             Combo.Changed += delegate {
                 if(Combo.ActiveProfile != null) {
                     ProfileConfiguration.SaveActiveProfile(Combo.ActiveProfile, configurationId);
-                    SetDescription();
+                    description.Update ();
                 }
             };
             
             Spacing = 5;
             PackStart(editor, true, true, 0);
-            
-            bool expand = parent != null;
-            
-            if(parent == null) {
-                parent = this;
-            }
-            
-            parent.PackStart(description, expand, expand, 0);
-        }
-        
-        private void SetDescription()
-        {
-            description.Markup = String.Format ("<small><i>{0}</i></small>", 
-                GLib.Markup.EscapeText (Combo.ActiveProfile.Description));
+            description.PackInto (parent ?? this, parent != null);
         }
         
         public ProfileComboBox Combo {

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Preferences.Gui/DescriptionLabel.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Preferences.Gui/DescriptionLabel.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Preferences.Gui/DescriptionLabel.cs	Thu Sep  4 18:13:05 2008
@@ -0,0 +1,70 @@
+//
+// DescriptionLabel.cs
+//
+// Authors:
+//   Gabriel Burt <gburt 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 Gtk;
+using Hyena.Widgets;
+
+namespace Banshee.Preferences.Gui
+{
+    public class DescriptionLabel : WrapLabel
+    {
+        public delegate string DescriptionHandler ();
+        private DescriptionHandler handler;
+        
+        public DescriptionLabel (string text) : base ()
+        {
+            Set (text);
+            Show ();
+        }
+
+        public DescriptionLabel (DescriptionHandler handler) : base ()
+        {
+            this.handler = handler;
+            Update ();
+            Show ();
+        }
+
+        public void Update ()
+        {
+            if (handler != null) {
+                Set (handler ());
+            }
+        }
+        
+        public void PackInto (Box parent, bool expand)
+        {
+            parent.PackStart (this, expand, expand, 0);
+        }
+
+        private void Set (string text)
+        {
+            Markup = String.Format ("<small><i>{0}</i></small>", GLib.Markup.EscapeText (text));
+        }
+    }
+}

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Preferences.Gui/WidgetFactory.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Preferences.Gui/WidgetFactory.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Preferences.Gui/WidgetFactory.cs	Thu Sep  4 18:13:05 2008
@@ -60,10 +60,16 @@
             if (widget != null) {
                 preference.Changed += OnPreferenceChanged;
                 //widget.Destroyed += OnWidgetDestroyed;
-                return widget;
+            }
+
+            if (preference.ShowDescription) {
+                VBox box = new VBox ();
+                box.PackStart (widget, false, false, 0);
+                new DescriptionLabel (preference.Description).PackInto (box, false);
+                widget = box;
             }
             
-            return null;
+            return widget;
         }
 
         public static Widget GetMnemonicWidget (PreferenceBase preference)
@@ -121,7 +127,7 @@
             {
                 this.preference = preference;
                 string value = (string)preference.BoxedValue;
-                Text = value == null ? String.Empty : value;
+                Text = value ?? String.Empty;
                 sync = true;
             }
             

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/FilteredListSourceContents.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/FilteredListSourceContents.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/FilteredListSourceContents.cs	Thu Sep  4 18:13:05 2008
@@ -132,7 +132,9 @@
             }
             
             ServiceManager.SourceManager.ActiveSourceChanged += delegate {
-                browser_container.Visible = ActiveSourceCanHasBrowser ? BrowserVisible.Get () : false; 
+                Banshee.Base.ThreadAssist.ProxyToMain (delegate {
+                    browser_container.Visible = ActiveSourceCanHasBrowser ? BrowserVisible.Get () : false;
+                });
             };
             
             NoShowAll = true;

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceComboBox.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceComboBox.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceComboBox.cs	Thu Sep  4 18:13:05 2008
@@ -49,11 +49,11 @@
             Model = store;
             
             ServiceManager.SourceManager.ActiveSourceChanged += delegate { 
-                UpdateActiveSource (); 
+                Banshee.Base.ThreadAssist.ProxyToMain (UpdateActiveSource);
             };
             
             ServiceManager.SourceManager.SourceUpdated += delegate {
-                QueueDraw ();
+                Banshee.Base.ThreadAssist.ProxyToMain (QueueDraw);                    
             };
             
             store.Refresh ();

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceModel.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceModel.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceModel.cs	Thu Sep  4 18:13:05 2008
@@ -64,6 +64,8 @@
 
     public class SourceModel : TreeStore
     {
+        private object sync = new object ();
+
         public event SourceRowEventHandler SourceRowInserted;
         public event SourceRowEventHandler SourceRowRemoved;
         
@@ -85,12 +87,16 @@
         
         private void OnSourceAdded (SourceAddedArgs args)
         {
-            AddSource (args.Source);
+            Banshee.Base.ThreadAssist.ProxyToMain (delegate {
+                AddSource (args.Source);
+            });
         }
         
         private void OnSourceRemoved (SourceEventArgs args)
         {
-            RemoveSource (args.Source);
+            Banshee.Base.ThreadAssist.ProxyToMain (delegate {
+                RemoveSource (args.Source);
+            });
         }
         
         protected virtual void OnSourceRowInserted (Source source, TreeIter iter, TreeIter parentIter)
@@ -204,49 +210,53 @@
 
         public void AddSource (Source source, TreeIter parent)
         {
-            // Don't add duplicates
-            if (!FindSource (source).Equals (TreeIter.Zero)) {
-                return;
-            }
-            
-            // Don't add a child source before its parent
-            if (parent.Equals (TreeIter.Zero) && source.Parent != null) {
-                return;
-            }
-            
-            int position = source.Order;
-            
-            TreeIter iter = parent.Equals (TreeIter.Zero)
-                ? InsertNode (position) 
-                : InsertNode (parent, position);
-            
-            SetValue (iter, 0, source);
-            SetValue (iter, 1, source.Order);
-            SetValue (iter, 2, false);
-
-            lock (source.Children) {
-                foreach (Source child in source.Children) {
-                    AddSource (child, iter);
+            lock (sync) {
+                // Don't add duplicates
+                if (!FindSource (source).Equals (TreeIter.Zero)) {
+                    return;
+                }
+                
+                // Don't add a child source before its parent
+                if (parent.Equals (TreeIter.Zero) && source.Parent != null) {
+                    return;
+                }
+                
+                int position = source.Order;
+                
+                TreeIter iter = parent.Equals (TreeIter.Zero)
+                    ? InsertNode (position) 
+                    : InsertNode (parent, position);
+                
+                SetValue (iter, 0, source);
+                SetValue (iter, 1, source.Order);
+                SetValue (iter, 2, false);
+
+                lock (source.Children) {
+                    foreach (Source child in source.Children) {
+                        AddSource (child, iter);
+                    }
                 }
+                
+                source.ChildSourceAdded += OnSourceChildSourceAdded; 
+                source.ChildSourceRemoved += OnSourceChildSourceRemoved;
+                
+                OnSourceRowInserted (source, iter, parent);
             }
-            
-            source.ChildSourceAdded += OnSourceChildSourceAdded; 
-            source.ChildSourceRemoved += OnSourceChildSourceRemoved;
-            
-            OnSourceRowInserted (source, iter, parent);
         }
         
         public void RemoveSource (Source source)
         {
-            TreeIter iter = FindSource (source);
-            if (!iter.Equals (TreeIter.Zero)) {
-                Remove (ref iter);
+            lock (sync) {
+                TreeIter iter = FindSource (source);
+                if (!iter.Equals (TreeIter.Zero)) {
+                    Remove (ref iter);
+                }
+                
+                source.ChildSourceAdded -= OnSourceChildSourceAdded;
+                source.ChildSourceRemoved -= OnSourceChildSourceRemoved;
+              
+                OnSourceRowRemoved (source, iter);
             }
-            
-            source.ChildSourceAdded -= OnSourceChildSourceAdded;
-            source.ChildSourceRemoved -= OnSourceChildSourceRemoved;
-          
-            OnSourceRowRemoved (source, iter);
         }
         
         public void Refresh ()
@@ -259,12 +269,16 @@
         
         private void OnSourceChildSourceAdded (SourceEventArgs args)
         {
-            AddSource (args.Source, FindSource (args.Source.Parent));
+            Banshee.Base.ThreadAssist.ProxyToMain (delegate {
+                AddSource (args.Source, FindSource (args.Source.Parent));
+            });
         }
         
         private void OnSourceChildSourceRemoved (SourceEventArgs args)
         {
-            RemoveSource (args.Source);
+            Banshee.Base.ThreadAssist.ProxyToMain (delegate {
+                RemoveSource (args.Source);
+            });
         }
         
 #endregion

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceView.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceView.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceView.cs	Thu Sep  4 18:13:05 2008
@@ -102,7 +102,7 @@
         private void ConnectEvents ()
         {
             ServiceManager.SourceManager.ActiveSourceChanged += delegate (SourceEventArgs args) {
-                ResetSelection ();
+                Banshee.Base.ThreadAssist.ProxyToMain (ResetSelection);
             };
             
             ServiceManager.SourceManager.SourceUpdated += delegate (SourceEventArgs args) {
@@ -118,10 +118,11 @@
             };
             
             ServiceManager.PlaybackController.NextSourceChanged += delegate {
-                QueueDraw ();
+                Banshee.Base.ThreadAssist.ProxyToMain (QueueDraw);
             };
             
             notify_stage.ActorStep += delegate (Actor<TreeIter> actor) {
+                Banshee.Base.ThreadAssist.AssertInMainThread ();
                 if (!store.IterIsValid (actor.Target)) {
                     return false;
                 }

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Makefile.am
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Makefile.am	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Makefile.am	Thu Sep  4 18:13:05 2008
@@ -113,6 +113,7 @@
 	Banshee.MediaProfiles.Gui/ProfileConfigureButton.cs \
 	Banshee.Playlist.Gui/PlaylistExportDialog.cs \
 	Banshee.Preferences.Gui/DefaultPreferenceWidgets.cs \
+	Banshee.Preferences.Gui/DescriptionLabel.cs \
 	Banshee.Preferences.Gui/NotebookPage.cs \
 	Banshee.Preferences.Gui/PreferenceDialog.cs \
 	Banshee.Preferences.Gui/SectionBox.cs \

Modified: trunk/banshee/src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp/MtpSource.cs
==============================================================================
--- trunk/banshee/src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp/MtpSource.cs	(original)
+++ trunk/banshee/src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp/MtpSource.cs	Thu Sep  4 18:13:05 2008
@@ -166,7 +166,7 @@
                     if ((track_id = DatabaseTrackInfo.GetTrackIdForUri (MtpTrackInfo.GetPathFromMtpTrack (mtp_track), source_ids)) > 0) {
                         track_map[track_id] = mtp_track;
                     } else {
-                        MtpTrackInfo track = new MtpTrackInfo (mtp_track);
+                        MtpTrackInfo track = new MtpTrackInfo (mtp_device, mtp_track);
                         track.PrimarySource = this;
                         track.Save (false);
                         track_map[track.TrackId] = mtp_track;
@@ -199,24 +199,23 @@
             get { return !(IsAdding || IsDeleting); }
         }
 
+        private static SafeUri empty_file = new SafeUri (Paths.Combine (Paths.ApplicationCache, "mtp.mp3"));
         protected override void OnTracksDeleted ()
         {
             // Hack to get the disk usage indicate to be accurate, which seems to
             // only be updated when tracks are added, not removed.
-            SafeUri empty_file = new SafeUri (Paths.Combine (Paths.ApplicationCache, "mtp.mp3"));
             try {
-                using (System.IO.TextWriter writer = new System.IO.StreamWriter (Banshee.IO.File.OpenWrite (empty_file, true))) {
-                    writer.Write ("foo");
-                }
-                Track mtp_track = new Track (System.IO.Path.GetFileName (empty_file.LocalPath), 3);
                 lock (mtp_device) {
+                    using (System.IO.TextWriter writer = new System.IO.StreamWriter (Banshee.IO.File.OpenWrite (empty_file, true))) {
+                        writer.Write ("foo");
+                    }
+                    Track mtp_track = new Track (System.IO.Path.GetFileName (empty_file.LocalPath), 3);
+
                     mtp_device.UploadTrack (empty_file.AbsolutePath, mtp_track, mtp_device.MusicFolder);
                     mtp_device.Remove (mtp_track);
+                    Banshee.IO.File.Delete (empty_file);
                 }
-            } finally {
-                Banshee.IO.File.Delete (empty_file);
-            }
-
+            } catch {}
             base.OnTracksDeleted ();
         }
 
@@ -265,7 +264,7 @@
             bool video = (track.MediaAttributes & TrackMediaAttributes.VideoStream) != 0;
             Console.WriteLine ("Sending file {0}, is video? {1}", fromUri.LocalPath, video);
             lock (mtp_device) {
-                mtp_device.UploadTrack (fromUri.LocalPath, mtp_track, video ? mtp_device.VideoFolder : mtp_device.MusicFolder, OnUploadProgress);
+                mtp_device.UploadTrack (fromUri.LocalPath, mtp_track, GetFolderForTrack (track), OnUploadProgress);
             }
 
             // Add/update album art
@@ -295,12 +294,21 @@
                 }
             }
 
-            MtpTrackInfo new_track = new MtpTrackInfo (mtp_track);
+            MtpTrackInfo new_track = new MtpTrackInfo (mtp_device, mtp_track);
             new_track.PrimarySource = this;
             new_track.Save (false);
             track_map[new_track.TrackId] = mtp_track;
         }
 
+        private Folder GetFolderForTrack (TrackInfo track)
+        {
+            if (track.HasAttribute (TrackMediaAttributes.Podcast))
+                return mtp_device.PodcastFolder;
+            else if (track.HasAttribute (TrackMediaAttributes.VideoStream))
+                return mtp_device.VideoFolder;
+            else
+                return mtp_device.MusicFolder;
+        }
 
         private int OnUploadProgress (ulong sent, ulong total, IntPtr data)
         {
@@ -333,17 +341,9 @@
         public Track TrackInfoToMtpTrack (TrackInfo track, SafeUri fromUri)
         {
 			Track f = new Track (System.IO.Path.GetFileName (fromUri.LocalPath), (ulong) Banshee.IO.File.GetSize (fromUri));
-			f.Album = track.AlbumTitle;
-			f.Artist = track.ArtistName;
-			f.Duration = (uint)track.Duration.TotalMilliseconds;
-			f.Genre = track.Genre;
-			f.Rating = (ushort)(track.Rating * 20);
-			f.Title = track.TrackTitle;
-			f.TrackNumber = (ushort)track.TrackNumber;
-			f.UseCount = (uint)track.PlayCount;
-            f.ReleaseDate = track.Year + "0101T0000.0";
+            MtpTrackInfo.ToMtpTrack (track, f);
             return f;
-		}
+        }
 
         public override void Dispose ()
         {

Modified: trunk/banshee/src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp/MtpTrackInfo.cs
==============================================================================
--- trunk/banshee/src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp/MtpTrackInfo.cs	(original)
+++ trunk/banshee/src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp/MtpTrackInfo.cs	Thu Sep  4 18:13:05 2008
@@ -30,7 +30,10 @@
 using System.IO;
 
 using Banshee.Base;
+using Banshee.Collection;
 using Banshee.Collection.Database;
+using Banshee.ServiceStack;
+using Banshee.MediaProfiles;
 
 using Mtp;
 
@@ -49,7 +52,7 @@
             return String.Format ("mtp://{0}/{1}", track.FileId, track.FileName);
         }
         
-        public MtpTrackInfo (Track file) : base()
+        public MtpTrackInfo (MtpDevice device, Track file) : base()
 		{
             this.file = file;
 			
@@ -61,9 +64,21 @@
             rating = file.Rating < 0 ? 0 : (file.Rating / 20);
             TrackTitle = file.Title;
             TrackNumber = file.TrackNumber < 0 ? 0 : (int)file.TrackNumber;
-            Year = (file.ReleaseDate != null && file.ReleaseDate.Length >= 4) ? Int32.Parse (file.ReleaseDate.Substring(0, 4)) : 0;
+            Year = file.Year;
             FileSize = (long)file.FileSize;
 
+            MediaAttributes = TrackMediaAttributes.AudioStream;
+            if (device != null) {
+                SetAttributeIf (file.InFolder (device.PodcastFolder) || Genre == "Podcast", TrackMediaAttributes.Podcast);
+                SetAttributeIf (file.InFolder (device.MusicFolder), TrackMediaAttributes.Music);
+                SetAttributeIf (file.InFolder (device.VideoFolder), TrackMediaAttributes.VideoStream);
+            }
+            // TODO set VideoStream for video podcast episodes
+            /*Profile profile = ServiceManager.Get<MediaProfileManager> ().GetProfileForExtension (System.IO.Path.GetExtension (file.FileName));
+            if (profile != null) {
+                profile.
+            }*/
+
             // This can be implemented if there's enough people requesting it
             CanPlay = false;
             CanSaveToDatabase = true;
@@ -74,6 +89,19 @@
 			// Set a URI even though it's not actually accessible through normal API's.
 			Uri = new SafeUri (GetPathFromMtpTrack (file));
         }
+
+        internal static void ToMtpTrack (TrackInfo track, Track f)
+        {
+			f.Album = track.AlbumTitle;
+			f.Artist = track.ArtistName;
+			f.Duration = (uint)track.Duration.TotalMilliseconds;
+			f.Genre = track.Genre;
+			f.Rating = (ushort)(track.Rating * 20);
+			f.Title = track.TrackTitle;
+			f.TrackNumber = (ushort)track.TrackNumber;
+			f.UseCount = (uint)track.PlayCount;
+            f.Year = track.Year;
+		}
         
         /*public override bool Equals (object o)
         {

Added: trunk/banshee/src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp/Tests/MtpDapTests.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp/Tests/MtpDapTests.cs	Thu Sep  4 18:13:05 2008
@@ -0,0 +1,102 @@
+//
+// MtpDapTests.cs
+//
+// Author:
+//   Gabriel Burt <gburt 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.
+//
+
+#if ENABLE_TESTS
+
+using System;
+using NUnit.Framework;
+
+using Hyena;
+using Mtp;
+
+using Banshee.Collection;
+using Banshee.Dap.Mtp;
+    
+namespace Banshee.Dap.Mtp
+{
+    [TestFixture]
+    public class MtpDapTests
+    {
+        [Test]
+        public void MtpToBansheeTrack ()
+        {
+            Track track = new Track ("foo.mp3", 1000);
+            track.Album = "Mtp Album";
+            track.Artist = "Mtp Artist";
+            track.Title = "Mtp Title";
+            track.Duration = (uint) (1000 * 132.2);
+            track.Rating = 80;
+            track.TrackNumber = 3;
+
+            TrackInfo track_info = new MtpTrackInfo (null, track);
+            Assert.AreEqual ("Mtp Artist", track_info.ArtistName);
+            Assert.AreEqual ("Mtp Album", track_info.AlbumTitle);
+            Assert.AreEqual ("Mtp Title", track_info.TrackTitle);
+            Assert.AreEqual (132.2, track_info.Duration.TotalSeconds);
+            Assert.AreEqual (4, track_info.Rating);
+            Assert.AreEqual (3, track_info.TrackNumber);
+            Assert.AreEqual (0, track_info.Year);
+
+            track.Year = 1983;
+            track_info = new MtpTrackInfo (null, track);
+            Assert.AreEqual (1983, track_info.Year);
+        }
+
+        [Test]
+        public void BansheeToMtpTrack ()
+        {
+            TrackInfo track_info = new TrackInfo ();
+            track_info.ArtistName = "Banshee Artist";
+            track_info.AlbumTitle = "Banshee Album";
+            track_info.TrackTitle = "Banshee Title";
+            track_info.Year = 2003;
+            track_info.Duration = TimeSpan.FromSeconds (3600 * 1.32);
+            track_info.Rating = 2;
+            track_info.TrackNumber = 13;
+
+            Track track = new Track ("foo.mp3", 1000);
+            MtpTrackInfo.ToMtpTrack (track_info, track);
+
+            Assert.AreEqual ("Banshee Artist", track.Artist);
+            Assert.AreEqual ("Banshee Album", track.Album);
+            Assert.AreEqual ("Banshee Title", track.Title);
+            Assert.AreEqual (1000 * 3600 * 1.32, track.Duration);
+            Assert.AreEqual (40, track.Rating);
+            Assert.AreEqual (13, track.TrackNumber);
+            Assert.AreEqual (2003, track.Year);
+
+            Console.WriteLine ("WOO, done!");
+
+            //track.ReleaseDate = "00000101T0000.00";
+            //track_info = new MtpTrackInfo (track);
+            //Assert.AreEqual (0, track_info.Year);
+        }
+    }
+}
+
+#endif

Modified: trunk/banshee/src/Dap/Banshee.Dap.Mtp/Makefile.am
==============================================================================
--- trunk/banshee/src/Dap/Banshee.Dap.Mtp/Makefile.am	(original)
+++ trunk/banshee/src/Dap/Banshee.Dap.Mtp/Makefile.am	Thu Sep  4 18:13:05 2008
@@ -5,7 +5,8 @@
 
 SOURCES =  \
 	Banshee.Dap.Mtp/MtpSource.cs \
-	Banshee.Dap.Mtp/MtpTrackInfo.cs
+	Banshee.Dap.Mtp/MtpTrackInfo.cs \
+	Banshee.Dap.Mtp/Tests/MtpDapTests.cs
 
 RESOURCES = Banshee.Dap.Mtp.addin.xml
 

Modified: trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap.Gui/DapActions.cs
==============================================================================
--- trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap.Gui/DapActions.cs	(original)
+++ trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap.Gui/DapActions.cs	Thu Sep  4 18:13:05 2008
@@ -38,7 +38,7 @@
     public class DapActions : BansheeActionGroup
     {
         private DapSource dap;
-        public DapActions (DapSource dap) : base ("dap-actions")
+        public DapActions (DapSource dap) : base ("dap")
         {
             this.dap = dap;
             AddImportant (
@@ -49,16 +49,19 @@
             
             this["SyncDapAction"].IconName = Stock.Refresh;
             UpdateActions ();
+            dap.Sync.Updated += delegate { Banshee.Base.ThreadAssist.ProxyToMain (UpdateActions); };
         }
 
         private void UpdateActions ()
         {
-            UpdateAction ("SyncDapAction", dap.Sync.Enabled);
+            UpdateAction ("SyncDapAction", dap.Sync.Enabled && !dap.Sync.AutoSync);
         }
 
         private void OnSyncDap (object o, EventArgs args)
         {
-            dap.Sync.Sync ();
+            Banshee.Base.ThreadAssist.SpawnFromMain (delegate {
+                dap.Sync.Sync ();
+            });
         }
     }
 }

Modified: trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap.Gui/DapContent.cs
==============================================================================
--- trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap.Gui/DapContent.cs	(original)
+++ trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap.Gui/DapContent.cs	Thu Sep  4 18:13:05 2008
@@ -74,13 +74,18 @@
             vbox.PackStart (new HSeparator (), false, false, 0);
 
             dap_stats = new WrapLabel ();
-            dap.Sync.Updated += delegate { dap_stats.Text = dap.Sync.ToString (); };
+            dap.Sync.Updated += delegate { Banshee.Base.ThreadAssist.ProxyToMain (UpdateStatus); };
             dap_stats.Text = dap.Sync.ToString ();
             vbox.PackStart (dap_stats, false, false, 0);
             
             ShowAll ();
         }
 
+        private void UpdateStatus ()
+        {
+            dap_stats.Text = dap.Sync.ToString ();
+        }
+
         private void BuildActions ()
         {
             actions = new DapActions (dap);

Modified: trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap.Gui/DapInfoBar.cs
==============================================================================
--- trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap.Gui/DapInfoBar.cs	(original)
+++ trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap.Gui/DapInfoBar.cs	Thu Sep  4 18:13:05 2008
@@ -99,11 +99,13 @@
         
         private void OnSourceUpdated (object o, EventArgs args)
         {
-            try {
-                UpdateUsage ();
-            } catch (Exception e) {
-                Hyena.Log.Exception (e);
-            }
+            Banshee.Base.ThreadAssist.ProxyToMain (delegate {
+                try {
+                    UpdateUsage ();
+                } catch (Exception e) {
+                    Hyena.Log.Exception (e);
+                }
+            });
         }
         
         protected override void OnStyleSet (Style previous_style)

Modified: trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap/DapLibrarySync.cs
==============================================================================
--- trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap/DapLibrarySync.cs	(original)
+++ trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap/DapLibrarySync.cs	Thu Sep  4 18:13:05 2008
@@ -52,7 +52,7 @@
         private string conf_ns;
         private SchemaEntry<bool> enabled, sync_entire_library;
         private SchemaEntry<string[]> playlist_ids;
-        private SmartPlaylistSource sync_src, to_add;
+        private SmartPlaylistSource sync_src, to_add, to_remove;
         private Section library_prefs_section;
         
         #region Public Properties
@@ -68,6 +68,10 @@
         public Section PrefsSection {
             get { return library_prefs_section; }
         }
+
+        public LibrarySource Library {
+            get { return library; }
+        }
         
         #endregion
         
@@ -106,6 +110,18 @@
             BuildSyncLists ();
         }
 
+        internal void Dispose ()
+        {
+            if (to_add != null)
+                to_add.Unmap ();
+
+            if (to_remove != null)
+                to_remove.Unmap ();
+
+            if (sync_src != null)
+                sync_src.Unmap ();
+        }
+
         private void BuildPreferences ()
         {
             conf_ns = String.Format ("{0}.{1}", sync.ConfigurationNamespace, library.ConfigurationId);
@@ -119,9 +135,7 @@
             playlist_ids = sync.Dap.CreateSchema<string[]> (conf_ns, "playlist_ids", new string [0],
                 "If sync_entire_library is false, this contains a list of playlist ids specifically to sync", "");
 
-            library_prefs_section = new Section (String.Format ("{0} sync", library.Name),
-                //String.Format (Catalog.GetString ("{0}"), library.Name)
-                library.Name, 0);
+            library_prefs_section = new Section (String.Format ("{0} sync", library.Name), library.Name, 0);
             library_prefs_section.Add<bool> (enabled);
         }
 
@@ -131,6 +145,8 @@
             sync_src = new SmartPlaylistSource ("sync_list", library.DbId);
             sync_src.IsTemporary = true;
             sync_src.Save ();
+            sync_src.AddCondition (library.AttributesCondition);
+            sync_src.AddCondition (library.SyncCondition);
 
             // This is the same as the previous list with the items that are already on the device removed
             to_add = new SmartPlaylistSource ("to_add", library.DbId);
@@ -141,12 +157,24 @@
             to_add.DatabaseTrackModel.AddCondition (String.Format (
                 "MetadataHash NOT IN (SELECT MetadataHash FROM CoreTracks WHERE PrimarySourceId = {0})", sync.Dap.DbId
             ));
+
+            // Any items on the device that aren't in the sync lists need to be removed
+            to_remove = new SmartPlaylistSource ("to_remove", sync.Dap.DbId);
+            to_remove.IsTemporary = true;
+            to_remove.Save ();
+            to_remove.AddCondition (library.AttributesCondition);
+            to_remove.AddCondition (String.Format (
+                @"MetadataHash NOT IN (SELECT MetadataHash FROM CoreTracks, CoreSmartPlaylistEntries 
+                    WHERE CoreSmartPlaylistEntries.SmartPlaylistID = {0} AND
+                        CoreTracks.TrackID = CoreSmartPlaylistEntries.TrackID)",
+                sync_src.DbId
+            ));
         }
         
         internal void CalculateSync ()
         {
             if (SyncEntireLibrary) {
-                to_add.ConditionTree = null;
+                sync_src.ConditionTree = null;
             } else if (SyncPlaylistIds.Length > 0) {
                 QueryListNode playlists_node = new QueryListNode (Keyword.Or);
                 foreach (AbstractPlaylistSource src in SyncPlaylists) {
@@ -160,22 +188,36 @@
             }
             sync_src.RefreshAndReload ();
             to_add.RefreshAndReload ();
+            to_remove.RefreshAndReload ();
         }
 
         public override string ToString ()
         {
-            return String.Format ("Sync calculated for {1}: to add: {0} items", to_add.Count, library.Name);
+            return String.Format ("Sync calculated for {1}: to add: {0} items, remove {2} items; sync_src.cacheid = {5}, to_add.cacheid = {3}, to_remove.cacheid = {4}", to_add.Count, library.Name, to_remove.Count,
+                                  to_add.DatabaseTrackModel.CacheId, to_remove.DatabaseTrackModel.CacheId, sync_src.DatabaseTrackModel.CacheId);
         }
         
         internal void Sync ()
         {
-            CalculateSync ();
-            
-            DoSyncPlaylists ();
-        }
-        
-        private void DoSyncPlaylists ()
-        {
+            if (Enabled) {
+                Log.InformationFormat ("Syncing {0}, in main thread? {1}", library, Banshee.Base.ThreadAssist.InMainThread);
+                if (to_remove.Count > 0) {
+                    Log.DebugFormat ("deleting items for {0} - {1} items; to_remove is smartplaylist {2}, with cachid {3}", library.Name, to_remove.Count, to_remove.DbId, to_remove.DatabaseTrackModel.CacheId);
+                    sync.Dap.DeleteAllTracks (to_remove);
+                }
+
+                if (to_add.Count > 0) {
+                    Log.DebugFormat ("adding {0} items to {1}", to_add.Count, library.Name);
+                    sync.Dap.AddAllTracks (to_add);
+                }
+
+                CalculateSync ();
+                sync.OnUpdated ();
+            }
+            //sync.Dap.AddAllTracks (to_add);
+
+            // Sync Playlists
+            /*
             // Remove all playlists
             foreach (Source child in sync.Dap.Children) {
                 if (child is AbstractPlaylistSource && !(child is MediaGroupSource)) {
@@ -189,15 +231,21 @@
 
             foreach (AbstractPlaylistSource src in SyncPlaylists) {
                 SyncPlaylist (src);
-            }
+            }*/
         }
         
-        private void SyncPlaylist (AbstractPlaylistSource from)
+        /*private void SyncPlaylist (AbstractPlaylistSource from)
         {
-            //PlaylistSource to = new PlaylistSource (from.Name, sync.Dap.DbId);
-            //to.Save ();
-            
-            // copy playlist/track entries based on metadatahash..
-        }
+            PlaylistSource to = new PlaylistSource (from.Name, sync.Dap.DbId);
+            to.Save ();
+
+            ServiceManager.DbConnection.Execute (
+                @"INSERT INTO CorePlaylistEntries (PlaylistID, TrackID)
+                    SELECT ?, TrackID FROM CoreTracks WHERE PrimarySourceID = ? AND MetadataHash IN (
+                        SELECT t.MetadataHash FROM CoreTracks t, CorePlaylistEntries e
+                            WHERE t.TrackID = e.TrackID AND e.PlaylistID = ?)",
+                to.DbId, sync.Dap.DbId, from.DbId
+            );
+        }*/
     }
 }

Modified: trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap/DapSource.cs
==============================================================================
--- trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap/DapSource.cs	(original)
+++ trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap/DapSource.cs	Thu Sep  4 18:13:05 2008
@@ -76,6 +76,11 @@
         protected MediaGroupSource VideoGroupSource {
             get { return video_group_source; }
         }
+
+        private MediaGroupSource podcast_group_source;
+        protected MediaGroupSource PodcastGroupSource {
+            get { return podcast_group_source; }
+        }
         
         protected DapSource ()
         {
@@ -84,7 +89,7 @@
         public virtual void DeviceInitialize (IDevice device)
         {
             this.device = device;
-            type_unique_id = device.Uuid;
+            TypeUniqueId = device.Uuid;
         }
 
         public override void Dispose ()
@@ -166,6 +171,7 @@
             
             AddChildSource (music_group_source = new MusicGroupSource (this));
             AddChildSource (video_group_source = new VideoGroupSource (this));
+            AddChildSource (podcast_group_source = new PodcastGroupSource (this));
 
             BuildPreferences ();
             Properties.Set<Banshee.Sources.Gui.ISourceContents> ("Nereid.SourceContents", new DapContent (this));
@@ -237,7 +243,11 @@
                 LoadFromDevice ();
                 OnTracksAdded ();
                 HideStatus ();
+
                 sync.CalculateSync ();
+                if (sync.AutoSync) {
+                    sync.Sync ();
+                }
             } catch (Exception e) {
                 Log.Exception (e);
             }

Modified: trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap/DapSync.cs
==============================================================================
--- trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap/DapSync.cs	(original)
+++ trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap/DapSync.cs	Thu Sep  4 18:13:05 2008
@@ -34,6 +34,7 @@
 using Hyena;
 using Hyena.Query;
 
+using Banshee.Base;
 using Banshee.Configuration;
 using Banshee.Sources;
 using Banshee.ServiceStack;
@@ -45,15 +46,16 @@
 
 namespace Banshee.Dap
 {
-    public sealed class DapSync
+    public sealed class DapSync : IDisposable
     {
         private DapSource dap;
         private string conf_ns;
         private List<DapLibrarySync> library_syncs = new List<DapLibrarySync> ();
         private SchemaEntry<bool> manually_manage, auto_sync;
-        private SmartPlaylistSource to_remove;
         private Section dap_prefs_section;
+        private PreferenceBase manually_manage_pref;//, auto_sync_pref;
         private List<Section> pref_sections = new List<Section> ();
+        private RateLimiter sync_limiter;
 
         public event Action<DapSync> Updated;
 
@@ -72,11 +74,11 @@
         }
         
         public bool Enabled {
-            get { return manually_manage.Get (); }
+            get { return !manually_manage.Get (); }
         }
         
         public bool AutoSync {
-            get { return auto_sync.Get (); }
+            get { return Enabled && auto_sync.Get (); }
         }
 
         public IEnumerable<Section> PreferenceSections {
@@ -88,10 +90,23 @@
         public DapSync (DapSource dapSource)
         {
             dap = dapSource;
+            sync_limiter = new RateLimiter (RateLimitedSync);
             BuildPreferences ();
             BuildSyncLists ();
         }
 
+        public void Dispose ()
+        {
+            foreach (LibrarySource source in Libraries) {
+                source.TracksAdded -= OnLibraryChanged;
+                source.TracksDeleted -= OnLibraryChanged;
+            }
+
+            foreach (DapLibrarySync sync in library_syncs) {
+                sync.Dispose ();
+            }
+        }
+
         private void BuildPreferences ()
         {
             conf_ns = String.Format ("{0}.{1}", dap.ConfigurationId, "sync");
@@ -102,49 +117,94 @@
             );
             
             auto_sync = dap.CreateSchema<bool> (conf_ns, "auto_sync", false,
-                Catalog.GetString ("Automatically sync the device when plugged in or the libraries change"),
+                Catalog.GetString ("Automatically sync the device when plugged in or when the libraries change"),
                 Catalog.GetString ("Begin synchronizing the device as soon as the device is plugged in or the libraries change.")
             );
 
             dap_prefs_section = new Section ("dap", Catalog.GetString ("Sync Preferences"), 0);
-            dap_prefs_section.Add (manually_manage);
-            dap_prefs_section.Add (auto_sync);
             pref_sections.Add (dap_prefs_section);
+
+            manually_manage_pref = dap_prefs_section.Add (manually_manage);
+            manually_manage_pref.ShowDescription = true;
+            manually_manage_pref.ShowLabel = false;
+            SchemaPreference<bool> auto_sync_pref = dap_prefs_section.Add (auto_sync);
+            auto_sync_pref.ValueChanged += OnAutoSyncChanged;
+            
+            //manually_manage_pref.Changed += OnEnabledChanged;
+            //auto_sync_pref.Changed += delegate { OnUpdated (); };
+            //OnEnabledChanged (null);
         }
 
         private void BuildSyncLists ()
         {
             int i = 0;
-            foreach (Source source in ServiceManager.SourceManager.Sources) {
-                if (source is LibrarySource) {
-                    DapLibrarySync library_sync = new DapLibrarySync (this, source as LibrarySource);
-                    library_syncs.Add (library_sync);
-                    pref_sections.Add (library_sync.PrefsSection);
-                    library_sync.PrefsSection.Order = ++i;
+            foreach (LibrarySource source in Libraries) {
+                DapLibrarySync library_sync = new DapLibrarySync (this, source);
+                library_syncs.Add (library_sync);
+                pref_sections.Add (library_sync.PrefsSection);
+                library_sync.PrefsSection.Order = ++i;
+            }
+
+            foreach (LibrarySource source in Libraries) {
+                source.TracksAdded += OnLibraryChanged;
+                source.TracksDeleted += OnLibraryChanged;
+            }
+
+            dap.TracksAdded += OnDapChanged;
+            dap.TracksDeleted += OnDapChanged;
+        }
+
+        /*private void OnEnabledChanged (Root pref)
+        {
+            Console.WriteLine ("got manual mng changed, Enabled = {0}", Enabled);
+            auto_sync_pref.Sensitive = Enabled;
+            foreach (Section section in pref_sections) {
+                if (section != dap_prefs_section) {
+                    section.Sensitive = Enabled;
+                 }
+             }
+            OnUpdated ();
+        }*/
+
+        private void OnAutoSyncChanged (Root preference)
+        {
+            if (AutoSync) {
+                Sync ();
+            }
+        }
+
+        private void OnDapChanged (Source sender, TrackEventArgs args)
+        {
+            if (!AutoSync) {
+                foreach (DapLibrarySync lib_sync in library_syncs) {
+                    lib_sync.CalculateSync ();
                 }
             }
+        }
 
-            bool first = true;
-            System.Text.StringBuilder sb = new System.Text.StringBuilder ();
-            foreach (DapLibrarySync sync in library_syncs) {
-                if (first) {
-                    first = false;
-                } else {
-                    sb.Append (",");
+        private void OnLibraryChanged (Source sender, TrackEventArgs args)
+        {
+            foreach (DapLibrarySync lib_sync in library_syncs) {
+                if (lib_sync.Library == sender) {
+                    if (AutoSync) {
+                        lib_sync.Sync ();
+                    } else {
+                        lib_sync.CalculateSync ();
+                        OnUpdated ();
+                    }
+                    break;
                 }
-                sb.Append (sync.SmartPlaylistId);
             }
+         }
 
-            // Any items on the device that aren't in the sync lists need to be removed
-            to_remove = new SmartPlaylistSource ("to_remove", dap.DbId);
-            to_remove.IsTemporary = true;
-            to_remove.Save ();
-            to_remove.DatabaseTrackModel.AddCondition (String.Format (
-                @"MetadataHash NOT IN (SELECT MetadataHash FROM CoreTracks, CoreSmartPlaylistEntries 
-                    WHERE CoreSmartPlaylistEntries.SmartPlaylistID IN ({0}) AND
-                        CoreTracks.TrackID = CoreSmartPlaylistEntries.TrackID)",
-                sb.ToString ()
-            ));
+        private IEnumerable<LibrarySource> Libraries {
+            get {
+                foreach (Source source in ServiceManager.SourceManager.Sources) {
+                    if (source is LibrarySource) {
+                        yield return source as LibrarySource;
+                    }
+                }
+            }
         }
         
         public int ItemCount {
@@ -164,9 +224,13 @@
             foreach (DapLibrarySync library_sync in library_syncs) {
                 library_sync.CalculateSync ();
             }
-            to_remove.RefreshAndReload ();
+
             Log.Information (ToString ());
+            OnUpdated ();
+        }
 
+        internal void OnUpdated ()
+        {
             Action<DapSync> handler = Updated;
             if (handler != null) {
                 handler (this);
@@ -180,14 +244,16 @@
                 sb.Append (library_sync.ToString ());
                 sb.Append ("\n");
             }
-            sb.Append (String.Format ("And {0} items to remove", to_remove.Count));
             return sb.ToString ();
         }
 
-        
         public void Sync ()
         {
-            // TODO: remove all items in to_remove
+            sync_limiter.Execute ();
+        }
+
+        private void RateLimitedSync ()
+        {
             foreach (DapLibrarySync library_sync in library_syncs) {
                 library_sync.Sync ();
             }

Modified: trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap/MusicGroupSource.cs
==============================================================================
--- trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap/MusicGroupSource.cs	(original)
+++ trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap/MusicGroupSource.cs	Thu Sep  4 18:13:05 2008
@@ -39,9 +39,7 @@
         {
             Properties.Remove ("Icon.Name");
             Properties.SetStringList ("Icon.Name", Banshee.ServiceStack.ServiceManager.SourceManager.MusicLibrary.Properties.GetStringList ("Icon.Name"));
-            
-            ConditionSql = String.Format ("(CoreTracks.Attributes & {0}) == {0} And (CoreTracks.Attributes & {1}) == 0",
-                (int)TrackMediaAttributes.AudioStream, (int)TrackMediaAttributes.VideoStream);
+            ConditionSql = Banshee.ServiceStack.ServiceManager.SourceManager.MusicLibrary.AttributesCondition;
         }
     }
 }

Modified: trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap/PodcastGroupSource.cs
==============================================================================
--- trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap/PodcastGroupSource.cs	(original)
+++ trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap/PodcastGroupSource.cs	Thu Sep  4 18:13:05 2008
@@ -0,0 +1,45 @@
+//
+// PodcastGroupSource.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.Collection;
+
+namespace Banshee.Dap
+{
+    public class PodcastGroupSource : MediaGroupSource
+    {
+        public PodcastGroupSource (DapSource parent) : base (parent, Catalog.GetString ("Podcasts"))
+        {
+            Properties.Remove ("Icon.Name");
+            Properties.SetStringList ("Icon.Name", "podcast");
+            ConditionSql = String.Format ("(CoreTracks.Attributes & {0}) != 0", (int)TrackMediaAttributes.Podcast);
+        }
+    }
+}

Modified: trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap/VideoGroupSource.cs
==============================================================================
--- trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap/VideoGroupSource.cs	(original)
+++ trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap/VideoGroupSource.cs	Thu Sep  4 18:13:05 2008
@@ -39,9 +39,7 @@
         {
             Properties.Remove ("Icon.Name");
             Properties.SetStringList ("Icon.Name", Banshee.ServiceStack.ServiceManager.SourceManager.VideoLibrary.Properties.GetStringList ("Icon.Name"));
-            
-            ConditionSql = String.Format ("(CoreTracks.Attributes & {0}) == {0}",
-                (int)(TrackMediaAttributes.AudioStream | TrackMediaAttributes.VideoStream));
+            ConditionSql = Banshee.ServiceStack.ServiceManager.SourceManager.VideoLibrary.AttributesCondition;
         }
     }
 }

Modified: trunk/banshee/src/Dap/Banshee.Dap/Makefile.am
==============================================================================
--- trunk/banshee/src/Dap/Banshee.Dap/Makefile.am	(original)
+++ trunk/banshee/src/Dap/Banshee.Dap/Makefile.am	Thu Sep  4 18:13:05 2008
@@ -16,6 +16,7 @@
 	Banshee.Dap/InvalidDeviceException.cs \
 	Banshee.Dap/MediaGroupSource.cs \
 	Banshee.Dap/MusicGroupSource.cs \
+	Banshee.Dap/PodcastGroupSource.cs \
 	Banshee.Dap/RemovableSource.cs \
 	Banshee.Dap/VideoGroupSource.cs
 

Modified: trunk/banshee/src/Extensions/Banshee.AudioCd/Banshee.AudioCd/AudioCdSource.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.AudioCd/Banshee.AudioCd/AudioCdSource.cs	(original)
+++ trunk/banshee/src/Extensions/Banshee.AudioCd/Banshee.AudioCd/AudioCdSource.cs	Thu Sep  4 18:13:05 2008
@@ -55,6 +55,7 @@
         {
             this.service = service;
             this.disc_model = discModel;
+            TypeUniqueId = discModel.Title;
             
             Properties.SetString ("TrackView.ColumnControllerXml", String.Format (@"
                 <column-controller>
@@ -254,10 +255,6 @@
 
 #region Source Overrides
 
-        protected override string TypeUniqueId {
-            get { return "audio-cd"; }
-        }
-        
         public override int Count {
             get { return disc_model.Count; }
         }

Modified: trunk/banshee/src/Extensions/Banshee.CoverArt/Banshee.CoverArt/CoverArtService.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.CoverArt/Banshee.CoverArt/CoverArtService.cs	(original)
+++ trunk/banshee/src/Extensions/Banshee.CoverArt/Banshee.CoverArt/CoverArtService.cs	Thu Sep  4 18:13:05 2008
@@ -98,6 +98,7 @@
         
         private void Initialize ()
         {            
+            Banshee.Base.ThreadAssist.AssertInMainThread ();
             actions = new ActionGroup ("CoverArt");
             
             ActionEntry[] action_list = new ActionEntry [] {
@@ -123,22 +124,24 @@
             if (disposed) {
                 return;
             }
+
+            Banshee.Base.ThreadAssist.ProxyToMain (delegate {
+                Gtk.Action fetch_action = action_service.GlobalActions["FetchCoverArtAction"];
+                if (fetch_action != null) {
+                    action_service.GlobalActions.Remove (fetch_action);
+                }
+                
+                action_service.RemoveActionGroup ("CoverArt");
+                action_service.UIManager.RemoveUi (ui_manager_id);
+                
+                actions = null;
+                action_service = null;
+                
+                ServiceManager.SourceManager.MusicLibrary.TracksAdded -= OnTracksAdded;
+                ServiceManager.SourceManager.MusicLibrary.TracksChanged -= OnTracksChanged;
             
-            Gtk.Action fetch_action = action_service.GlobalActions["FetchCoverArtAction"];
-            if (fetch_action != null) {
-                action_service.GlobalActions.Remove (fetch_action);
-            }
-            
-            action_service.RemoveActionGroup ("CoverArt");
-            action_service.UIManager.RemoveUi (ui_manager_id);
-            
-            actions = null;
-            action_service = null;
-            
-            ServiceManager.SourceManager.MusicLibrary.TracksAdded -= OnTracksAdded;
-            ServiceManager.SourceManager.MusicLibrary.TracksChanged -= OnTracksChanged;
-            
-            disposed = true;
+                disposed = true;
+            });
         }
         
         public void FetchCoverArt ()

Modified: trunk/banshee/src/Extensions/Banshee.Daap/Banshee.Daap/DaapContainerSource.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.Daap/Banshee.Daap/DaapContainerSource.cs	(original)
+++ trunk/banshee/src/Extensions/Banshee.Daap/Banshee.Daap/DaapContainerSource.cs	Thu Sep  4 18:13:05 2008
@@ -41,6 +41,7 @@
         public DaapContainerSource () :  base (Catalog.GetString ("Shared Music"), Catalog.GetString ("Shared Music"), 300)
         {
             Properties.SetStringList ("Icon.Name", "applications-internet", "network-server");
+            TypeUniqueId = "daap-container";
         }
         
         public override bool? AutoExpand {
@@ -54,9 +55,5 @@
         public override bool CanRename {
             get { return false; }
         }
-        
-        protected override string TypeUniqueId {
-            get { return "daap-container"; }
-        }
     }
 }

Modified: trunk/banshee/src/Extensions/Banshee.FileSystemQueue/Banshee.FileSystemQueue/FileSystemQueueSource.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.FileSystemQueue/Banshee.FileSystemQueue/FileSystemQueueSource.cs	(original)
+++ trunk/banshee/src/Extensions/Banshee.FileSystemQueue/Banshee.FileSystemQueue/FileSystemQueueSource.cs	Thu Sep  4 18:13:05 2008
@@ -51,13 +51,10 @@
         private bool play_enqueued = false;
         private string path_to_play;
         
-        protected override string TypeUniqueId {
-            get { return "file-system-queue"; }
-        }
-        
         public FileSystemQueueSource () : base (Catalog.GetString ("File System Queue"), 
             Catalog.GetString ("File System Queue"), "file-system-queue", 30)
         {
+            TypeUniqueId = "file-system-queue";
             Properties.SetString ("Icon.Name", "system-file-manager");
             Properties.Set<bool> ("AutoAddSource", false);
             IsLocal = true;
@@ -89,7 +86,7 @@
             actions_loaded = true;
             
             UpdateActions ();
-            ServiceManager.SourceManager.ActiveSourceChanged += delegate { UpdateActions (); };
+            ServiceManager.SourceManager.ActiveSourceChanged += delegate { Banshee.Base.ThreadAssist.ProxyToMain (UpdateActions); };
             TrackModel.Reloaded += OnTrackModelReloaded;
             
             Reload ();

Modified: trunk/banshee/src/Extensions/Banshee.InternetRadio/Banshee.InternetRadio/InternetRadioSource.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.InternetRadio/Banshee.InternetRadio/InternetRadioSource.cs	(original)
+++ trunk/banshee/src/Extensions/Banshee.InternetRadio/Banshee.InternetRadio/InternetRadioSource.cs	Thu Sep  4 18:13:05 2008
@@ -47,16 +47,13 @@
 {
     public class InternetRadioSource : PrimarySource, IDisposable
     {
-        protected override string TypeUniqueId {
-            get { return "internet-radio"; }
-        }
-        
         private InternetRadioSourceContents source_contents;
         private uint ui_id;
         
         public InternetRadioSource () : base (Catalog.GetString ("Radio"), Catalog.GetString ("Radio"), "internet-radio", 220)
         {
             Properties.SetString ("Icon.Name", "radio");
+            TypeUniqueId = "internet-radio";
             IsLocal = false;
             
             InternetRadioInitialize ();

Modified: trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/LastfmSource.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/LastfmSource.cs	(original)
+++ trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/LastfmSource.cs	Thu Sep  4 18:13:05 2008
@@ -68,13 +68,10 @@
         public LastfmActions Actions {
             get { return actions; }
         }
-        
-        protected override string TypeUniqueId {
-            get { return lastfm; }
-        }
 
         public LastfmSource () : base (lastfm, lastfm, 210)
         {
+            TypeUniqueId = lastfm;
             account = LastfmCore.Account;
 
             // We don't automatically connect to Last.fm, but load the last Last.fm

Modified: trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/StationSource.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/StationSource.cs	(original)
+++ trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/StationSource.cs	Thu Sep  4 18:13:05 2008
@@ -110,15 +110,12 @@
 
         private int dbid;
         
-        protected override string TypeUniqueId {
-            get { return Convert.ToString (dbid); }
-        }
-        
         // For StationSources that already exist in the db
         protected StationSource (LastfmSource lastfm, int dbId, string name, string type, string arg, int playCount) : base (generic_name, name, 150)
         {
             this.lastfm = lastfm;
             dbid = dbId;
+            TypeUniqueId = dbid.ToString ();
             Type = StationType.FindByName (type);
             Arg = arg;
             PlayCount = playCount;
@@ -179,6 +176,7 @@
             );
 
             dbid = ServiceManager.DbConnection.Execute (command);
+            TypeUniqueId = dbid.ToString ();
         }
 
         private void Update ()

Modified: trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Recommendations/RecommendationService.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Recommendations/RecommendationService.cs	(original)
+++ trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Recommendations/RecommendationService.cs	Thu Sep  4 18:13:05 2008
@@ -92,12 +92,12 @@
 
         private void OnActiveSourceChanged (EventArgs args)
         {
-            UpdateVisibility ();
+            Banshee.Base.ThreadAssist.ProxyToMain (UpdateVisibility);
         }
 
         private void OnSourceChanged (object sender, EventArgs args)
         {
-            UpdateVisibility ();
+            Banshee.Base.ThreadAssist.ProxyToMain (UpdateVisibility);
         }
 
         private void OnPlayerEvent (PlayerEventArgs args)

Modified: trunk/banshee/src/Extensions/Banshee.MiniMode/Banshee.MiniMode/SourceModel.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.MiniMode/Banshee.MiniMode/SourceModel.cs	(original)
+++ trunk/banshee/src/Extensions/Banshee.MiniMode/Banshee.MiniMode/SourceModel.cs	Thu Sep  4 18:13:05 2008
@@ -91,11 +91,13 @@
                 AddSource(child, AppendNode(iter));
             }
 
-            source.ChildSourceAdded += delegate(SourceEventArgs e) {
-                AddSource(e.Source, AppendNode(iter));
+            source.ChildSourceAdded += delegate (SourceEventArgs e) {
+                Banshee.Base.ThreadAssist.ProxyToMain (delegate {
+                    AddSource(e.Source, AppendNode(iter));
+                });
             };
 
-            source.ChildSourceRemoved += delegate(SourceEventArgs e) {
+            source.ChildSourceRemoved += delegate (SourceEventArgs e) {
                 RemoveSource(e.Source);
             };
         }

Modified: trunk/banshee/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/NowPlayingSource.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/NowPlayingSource.cs	(original)
+++ trunk/banshee/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/NowPlayingSource.cs	Thu Sep  4 18:13:05 2008
@@ -44,13 +44,10 @@
     {
         private TrackInfo transitioned_track;
         private NowPlayingInterface now_playing_interface;
-
-        protected override string TypeUniqueId {
-            get { return "now-playing"; }
-        }
         
         public NowPlayingSource () : base ("now-playing", Catalog.GetString ("Now Playing"), 10)
         {
+            TypeUniqueId = "now-playing";
             now_playing_interface = new NowPlayingInterface ();
         
             Properties.SetString ("Icon.Name", "applications-multimedia");

Modified: trunk/banshee/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueSource.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueSource.cs	(original)
+++ trunk/banshee/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueSource.cs	Thu Sep  4 18:13:05 2008
@@ -59,9 +59,12 @@
             get { return false; }
         }
         
-        public PlayQueueSource () : base (Catalog.GetString ("Play Queue"), null, 20)
+        public PlayQueueSource () : base (Catalog.GetString ("Play Queue"), 0)
         {
             BindToDatabase ();
+            TypeUniqueId = DbId.ToString ();
+            Initialize ();
+            AfterInitialized ();
             
             Order = 20;
             Properties.SetString ("Icon.Name", "source-playlist");
@@ -106,7 +109,7 @@
             actions_loaded = true;
             
             UpdateActions ();
-            ServiceManager.SourceManager.ActiveSourceChanged += delegate { UpdateActions (); };
+            ServiceManager.SourceManager.ActiveSourceChanged += delegate { Banshee.Base.ThreadAssist.ProxyToMain (UpdateActions); };
 
             // TODO listen to all primary sources, and handle transient primary sources
             ServiceManager.SourceManager.MusicLibrary.TracksChanged += HandleTracksChanged;

Modified: trunk/banshee/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Data/PodcastSource.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Data/PodcastSource.cs	(original)
+++ trunk/banshee/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Data/PodcastSource.cs	Thu Sep  4 18:13:05 2008
@@ -96,6 +96,9 @@
         public PodcastSource (string baseDirectory) : base (Catalog.GetString ("Podcasts"), "PodcastLibrary", 200)
         {
             this.baseDirectory = baseDirectory;
+            MediaTypes = TrackMediaAttributes.Podcast;
+            NotMediaTypes = TrackMediaAttributes.AudioBook;
+            SyncCondition = "substr(CoreTracks.Uri, 0, 4) != 'http'";
 
             // For now..
             SupportsPlaylists = false;

Modified: trunk/banshee/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Data/PodcastTrackInfo.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Data/PodcastTrackInfo.cs	(original)
+++ trunk/banshee/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Data/PodcastTrackInfo.cs	Thu Sep  4 18:13:05 2008
@@ -213,7 +213,6 @@
             Year = Item.PubDate.Year;
             CanPlay = true;
             Genre = Genre ?? "Podcast";
-            MediaAttributes |= TrackMediaAttributes.Podcast;
             ReleaseDate = Item.PubDate;
             MimeType = Item.Enclosure.MimeType;
             Duration = Item.Enclosure.Duration;
@@ -227,6 +226,8 @@
                     Banshee.Streaming.StreamTagger.TrackInfoMerge (this, file, true);
                 } catch {}
             }
+
+            MediaAttributes |= TrackMediaAttributes.Podcast;
         }
         
         protected override void ProviderSave ()

Modified: trunk/banshee/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Gui/PodcastActions.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Gui/PodcastActions.cs	(original)
+++ trunk/banshee/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Gui/PodcastActions.cs	Thu Sep  4 18:13:05 2008
@@ -161,8 +161,8 @@
 
             ServiceManager.SourceManager.ActiveSourceChanged += HandleActiveSourceChanged;
             
-            source.TrackModel.Selection.Changed += delegate { UpdateItemActions (); };
-            source.FeedModel.Selection.Changed += delegate { UpdateFeedActions (); };
+            source.TrackModel.Selection.Changed += delegate { Banshee.Base.ThreadAssist.ProxyToMain (UpdateItemActions); };
+            source.FeedModel.Selection.Changed += delegate { Banshee.Base.ThreadAssist.ProxyToMain (UpdateFeedActions); };
             
             UpdateFeedActions ();
             UpdateItemActions ();
@@ -179,8 +179,10 @@
 
         private void HandleActiveSourceChanged (SourceEventArgs args)
         {
-            UpdateFeedActions ();
-            UpdateItemActions ();
+            Banshee.Base.ThreadAssist.ProxyToMain (delegate {
+                UpdateFeedActions ();
+                UpdateItemActions ();
+            });
         }
 
 #endregion

Modified: trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteModelProvider.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteModelProvider.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteModelProvider.cs	Thu Sep  4 18:13:05 2008
@@ -670,29 +670,32 @@
             Dictionary<string, string> tables = new Dictionary<string,string> (virtual_columns.Count + 1);
             bool first_virtual = true;
             foreach (VirtualDatabaseColumn column in virtual_columns) {
-                if (first_virtual) {
-                    first_virtual = false;
-                } else {
-                    where_builder.Append (" AND ");
-                }
                 if (first) {
                     first = false;
                 } else {
                     select_builder.Append (',');
                 }
+
                 select_builder.Append (column.TargetTable);
                 select_builder.Append ('.');
                 select_builder.Append (column.Name);
+
+                bool table_not_joined = !tables.ContainsKey (column.TargetTable);
+                if (first_virtual) {
+                    first_virtual = false;
+                } else if (table_not_joined) {
+                    where_builder.Append (" AND ");
+                }
                 
-                where_builder.Append (column.TargetTable);
-                where_builder.Append ('.');
-                where_builder.Append (column.ForeignKey);
-                where_builder.Append (" = ");
-                where_builder.Append (TableName);
-                where_builder.Append ('.');
-                where_builder.Append (column.LocalKey);
+                if (table_not_joined) {
+                    where_builder.Append (column.TargetTable);
+                    where_builder.Append ('.');
+                    where_builder.Append (column.ForeignKey);
+                    where_builder.Append (" = ");
+                    where_builder.Append (TableName);
+                    where_builder.Append ('.');
+                    where_builder.Append (column.LocalKey);
                 
-                if (!tables.ContainsKey (column.TargetTable)) {
                     tables.Add (column.TargetTable, null);
                 }
             }

Modified: trunk/banshee/src/Libraries/Mtp/Mtp/MtpDevice.cs
==============================================================================
--- trunk/banshee/src/Libraries/Mtp/Mtp/MtpDevice.cs	(original)
+++ trunk/banshee/src/Libraries/Mtp/Mtp/MtpDevice.cs	Thu Sep  4 18:13:05 2008
@@ -231,6 +231,7 @@
 			if (track == null)
 				throw new ArgumentNullException("track");
 
+            folder = folder ?? MusicFolder;
             track.trackStruct.parent_id = folder.FolderId;
 			
 			// We send the trackstruct by ref so that when the file_id gets filled in, our copy is updated

Modified: trunk/banshee/src/Libraries/Mtp/Mtp/Track.cs
==============================================================================
--- trunk/banshee/src/Libraries/Mtp/Mtp/Track.cs	(original)
+++ trunk/banshee/src/Libraries/Mtp/Mtp/Track.cs	Thu Sep  4 18:13:05 2008
@@ -64,6 +64,11 @@
 			set { trackStruct.date = value; }
 		}
 
+		public int Year {
+			get { return ReleaseDate == null || ReleaseDate.Length < 4 ? 0 : Int32.Parse (ReleaseDate.Substring(0, 4)); }
+			set { ReleaseDate = String.Format ("{0:0000}0101T0000.00", value); }
+		}
+
 		public uint Duration {
 			get { return trackStruct.duration; }
 			set { trackStruct.duration = value; }
@@ -141,6 +146,11 @@
 			this.device = device;
 			this.trackStruct = track;
 		}
+
+        public bool InFolder (Folder folder)
+        {
+            return folder != null && trackStruct.parent_id == folder.FolderId;
+        }
 		
 		public void Download (string path)
 		{

Modified: trunk/banshee/tests/Makefile.am
==============================================================================
--- trunk/banshee/tests/Makefile.am	(original)
+++ trunk/banshee/tests/Makefile.am	Thu Sep  4 18:13:05 2008
@@ -6,8 +6,8 @@
 	Hyena.dll \
 	Migo.dll \
 	Banshee.Core.dll \
-	Banshee.Services.dll
-
+	Banshee.Services.dll \
+	Banshee.Dap.Mtp.dll
 
 RUNNER = for asm in $${TEST_ASSEMBLIES}; do echo -e "\033[1mRunning tests on $${asm}...\033[0m"; TZ=America/Chicago LC_ALL=it_IT LANG=it_IT nunit-console2 /nologo $$asm; done
 



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