banshee r3872 - in trunk/banshee: . libbanshee src/Backends/Banshee.GStreamer/Banshee.GStreamer src/Core/Banshee.Core/Banshee.Collection src/Core/Banshee.Services src/Core/Banshee.Services/Banshee.Collection.Database src/Core/Banshee.Services/Banshee.Database src/Core/Banshee.Services/Banshee.MediaEngine src/Core/Banshee.Services/Banshee.PlaybackController src/Core/Banshee.ThickClient/Banshee.Collection.Gui src/Core/Banshee.ThickClient/Banshee.Gui.Widgets



Author: abock
Date: Sun May  4 21:42:09 2008
New Revision: 3872
URL: http://svn.gnome.org/viewvc/banshee?rev=3872&view=rev

Log:
2008-05-04  Aaron Bockover  <abock gnome org>

    * src/Core/Banshee.Services/Banshee.PlaybackController/PlaybackControllerService.cs:
    Added error handling so that no more than 20 attempts will be made to
    play from the active source if those attempts result in an error

    * src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackInfo.cs:
    Bind to the PlaybackError property to the LastStreamError column so any
    errors (missing codec, resource not found, etc.) are persisted in the
    database

    * src/Core/Banshee.Services/Banshee.Database/BansheeDbFormatMigrator.cs:
    Added a migration for adding the new LastStreamError column on CoreTracks

    * src/Core/Banshee.Services/Banshee.MediaEngine/NullPlayerEngine.cs:
    Updated to reflect API changes in the base class

    * src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEvent.cs: Added
    the loading state

    * src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngine.cs:
    Make Play/Pause abstract instead of virtual; do not set any event or
    state in Open and make the underlying engine responsible for these

    * src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngineService.cs:
    Changed the definition of IsPlaying to mean the engine is in one of
    playing, paused, or loaded states

    * src/Core/Banshee.Core/Banshee.Collection/TrackInfo.cs: made CanPlay
    return the set value and whether or not there is a playback error set

    * src/Backends/Banshee.GStreamer/Banshee.GStreamer/PlayerEngine.cs:
    Set the engine states based on state transitions from GStreamer proper
    instead of synthesizing so many based on API

    * src/Core/Banshee.ThickClient/Banshee.Collection.Gui/ColumnCellPlaybackIndicator.cs:
    Indicate an error if one is set on the track

    * src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/TrackInfoDisplay.cs:
    Updated to act on proper engine state

    * libbanshee/banshee-player.c:
    * libbanshee/banshee-player-pipeline.c:
    * libbanshee/banshee-player-missing-elements.c: Add some playbin checks
    to prevent warning messages from being spewed when playbin is torn down
    in some cases, particularly when there is a pipeline error



Modified:
   trunk/banshee/ChangeLog
   trunk/banshee/libbanshee/banshee-player-missing-elements.c
   trunk/banshee/libbanshee/banshee-player-pipeline.c
   trunk/banshee/libbanshee/banshee-player.c
   trunk/banshee/src/Backends/Banshee.GStreamer/Banshee.GStreamer/PlayerEngine.cs
   trunk/banshee/src/Core/Banshee.Core/Banshee.Collection/TrackInfo.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackInfo.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Database/BansheeDbFormatMigrator.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.MediaEngine/NullPlayerEngine.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngine.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngineService.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEvent.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.PlaybackController/PlaybackControllerService.cs
   trunk/banshee/src/Core/Banshee.Services/Makefile.am
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/ColumnCellPlaybackIndicator.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/TrackInfoDisplay.cs

Modified: trunk/banshee/libbanshee/banshee-player-missing-elements.c
==============================================================================
--- trunk/banshee/libbanshee/banshee-player-missing-elements.c	(original)
+++ trunk/banshee/libbanshee/banshee-player-missing-elements.c	Sun May  4 21:42:09 2008
@@ -71,7 +71,10 @@
     
     bp_slist_destroy (player->missing_element_details);
     player->missing_element_details = NULL;
-    gst_element_set_state (player->playbin, GST_STATE_READY);
+    
+    if (GST_IS_ELEMENT (player->playbin)) {
+        gst_element_set_state (player->playbin, GST_STATE_READY);
+    }
     
     if (player->error_cb != NULL) {
         player->error_cb (player, GST_CORE_ERROR, GST_CORE_ERROR_MISSING_PLUGIN, NULL, NULL);
@@ -137,19 +140,11 @@
     GstInstallPluginsReturn install_return;
     gchar **details;
     
-    if (old != GST_STATE_READY || new != GST_STATE_PAUSED) {
-        return;
-    }
-    
     g_return_if_fail (IS_BANSHEE_PLAYER (player));
     
-    if (player->missing_element_details == NULL) {
+    if (old != GST_STATE_READY || new != GST_STATE_PAUSED || player->install_plugins_context != NULL) {
         return;
-    }
-    
-    g_return_if_fail (player->install_plugins_context != NULL);
-    
-    if (player->install_plugins_noprompt) {
+    } else if (player->install_plugins_noprompt) {
         bp_missing_elements_handle_install_failed (player);
         return;
     }
@@ -159,7 +154,8 @@
     
     #ifdef GDK_WINDOWING_X11
     if (player->window != NULL) {
-        gst_install_plugins_context_set_xid (player->install_plugins_context, GDK_WINDOW_XWINDOW (player->window));
+        gst_install_plugins_context_set_xid (player->install_plugins_context, 
+            GDK_WINDOW_XWINDOW (player->window));
     }
     #endif
     

Modified: trunk/banshee/libbanshee/banshee-player-pipeline.c
==============================================================================
--- trunk/banshee/libbanshee/banshee-player-pipeline.c	(original)
+++ trunk/banshee/libbanshee/banshee-player-pipeline.c	Sun May  4 21:42:09 2008
@@ -62,7 +62,7 @@
 
     g_return_val_if_fail (IS_BANSHEE_PLAYER (player), FALSE);
     g_return_val_if_fail (message != NULL, FALSE);
-
+    
     switch (GST_MESSAGE_TYPE (message)) {
         case GST_MESSAGE_EOS: {
             if (player->eos_cb != NULL) {
@@ -75,7 +75,7 @@
             GstState old, new, pending;
             gst_message_parse_state_changed (message, &old, &new, &pending);
             
-            _bp_missing_elements_handle_state_changed (player, old, new);
+            //_bp_missing_elements_handle_state_changed (player, old, new);
             
             if (player->state_changed_cb != NULL) {
                 player->state_changed_cb (player, old, new, pending);

Modified: trunk/banshee/libbanshee/banshee-player.c
==============================================================================
--- trunk/banshee/libbanshee/banshee-player.c	(original)
+++ trunk/banshee/libbanshee/banshee-player.c	Sun May  4 21:42:09 2008
@@ -147,6 +147,8 @@
     // in case it is able to perform a fast seek to a track
     if (_bp_cdda_handle_uri (player, uri)) {
         return TRUE;
+    } else if (player->playbin == NULL) {
+        return FALSE;
     }
     
     // Set the pipeline to the proper state
@@ -197,8 +199,10 @@
 {
     g_return_val_if_fail (IS_BANSHEE_PLAYER (player), FALSE);
     
-    if (!gst_element_seek (player->playbin, 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH,
-        GST_SEEK_TYPE_SET, time_ms * GST_MSECOND, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) {
+    if (player->playbin == NULL || !gst_element_seek (player->playbin, 1.0, 
+        GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH,
+        GST_SEEK_TYPE_SET, time_ms * GST_MSECOND, 
+        GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) {
         g_warning ("Could not seek in stream");
         return FALSE;
     }
@@ -214,7 +218,7 @@
 
     g_return_val_if_fail (IS_BANSHEE_PLAYER (player), 0);
 
-    if (gst_element_query_position (player->playbin, &format, &position)) {
+    if (player->playbin != NULL && gst_element_query_position (player->playbin, &format, &position)) {
         return position / GST_MSECOND;
     }
     
@@ -229,7 +233,7 @@
 
     g_return_val_if_fail (IS_BANSHEE_PLAYER (player), 0);
 
-    if (gst_element_query_duration (player->playbin, &format, &duration)) {
+    if (player->playbin != NULL && gst_element_query_duration (player->playbin, &format, &duration)) {
         return duration / GST_MSECOND;
     }
     
@@ -243,7 +247,10 @@
     gboolean can_seek = TRUE;
     
     g_return_val_if_fail (IS_BANSHEE_PLAYER (player), FALSE);
-    g_return_val_if_fail (player->playbin != NULL, FALSE);
+    
+    if (player->playbin == NULL) {
+        return FALSE;
+    }
     
     query = gst_query_new_seeking (GST_FORMAT_TIME);
     if (!gst_element_query (player->playbin, query)) {

Modified: trunk/banshee/src/Backends/Banshee.GStreamer/Banshee.GStreamer/PlayerEngine.cs
==============================================================================
--- trunk/banshee/src/Backends/Banshee.GStreamer/Banshee.GStreamer/PlayerEngine.cs	(original)
+++ trunk/banshee/src/Backends/Banshee.GStreamer/Banshee.GStreamer/PlayerEngine.cs	Sun May  4 21:42:09 2008
@@ -40,9 +40,18 @@
 
 namespace Banshee.GStreamer
 {
+    internal enum GstState
+    {
+        VoidPending = 0,
+        Null = 1,
+        Ready = 2,
+        Paused = 3,
+        Playing = 4
+    }
+
     internal delegate void BansheePlayerEosCallback (IntPtr player);
     internal delegate void BansheePlayerErrorCallback (IntPtr player, uint domain, int code, IntPtr error, IntPtr debug);
-    internal delegate void BansheePlayerStateChangedCallback (IntPtr player, int old_state, int new_state, int pending_state);
+    internal delegate void BansheePlayerStateChangedCallback (IntPtr player, GstState old_state, GstState new_state, GstState pending_state);
     internal delegate void BansheePlayerIterateCallback (IntPtr player);
     internal delegate void BansheePlayerBufferingCallback (IntPtr player, int buffering_progress);
 
@@ -66,6 +75,7 @@
         
         private bool buffering_finished;
         private short pending_volume = -1;
+        private bool xid_is_set = false;
         
         public PlayerEngine ()
         {
@@ -99,6 +109,7 @@
             
             eos_callback = new BansheePlayerEosCallback (OnEos);
             error_callback = new BansheePlayerErrorCallback (OnError);
+            state_changed_callback = new BansheePlayerStateChangedCallback (OnStateChange);
             iterate_callback = new BansheePlayerIterateCallback (OnIterate);
             buffering_callback = new BansheePlayerBufferingCallback (OnBuffering);
             tag_found_callback = new GstTaggerTagFoundCallback (OnTagFound);
@@ -134,27 +145,32 @@
             // The GStreamer engine can use the XID of the main window if it ever
             // needs to bring up the plugin installer so it can be transient to
             // the main window.
-
-            IPropertyStoreExpose service = ServiceManager.Get<IService> ("GtkElementsService") as IPropertyStoreExpose;
-            if (service != null) {
-                bp_set_application_gdk_window (handle, service.PropertyStore.Get<IntPtr> ("PrimaryWindow.RawHandle"));
+            if (!xid_is_set) {
+                IPropertyStoreExpose service = ServiceManager.Get<IService> ("GtkElementsService") as IPropertyStoreExpose;
+                if (service != null) {
+                    bp_set_application_gdk_window (handle, service.PropertyStore.Get<IntPtr> ("PrimaryWindow.RawHandle"));
+                }
+                xid_is_set = true;
             }
                 
             IntPtr uri_ptr = GLib.Marshaller.StringToPtrGStrdup (uri.AbsoluteUri);
-            bp_open (handle, uri_ptr);
-            GLib.Marshaller.Free (uri_ptr);
+            try {
+                if (!bp_open (handle, uri_ptr)) {
+                    throw new ApplicationException ("Could not open resource");
+                }
+            } finally {
+                GLib.Marshaller.Free (uri_ptr);
+            }
         }
         
         public override void Play ()
         {
             bp_play (handle);
-            OnStateChanged (PlayerState.Playing);
         }
         
         public override void Pause ()
         {
             bp_pause (handle);
-            OnStateChanged (PlayerState.Paused);
         }
         
         public override void VideoExpose (IntPtr window, bool direct)
@@ -184,6 +200,23 @@
             OnEventChanged (PlayerEvent.Iterate);
         }
         
+        private void OnStateChange (IntPtr player, GstState old_state, GstState new_state, GstState pending_state)
+        {
+            if (old_state == GstState.Ready && new_state == GstState.Paused && pending_state == GstState.Playing) {
+                OnStateChanged (PlayerState.Loaded);
+                return;
+            } else if (old_state == GstState.Paused && new_state == GstState.Playing && pending_state == GstState.VoidPending) {
+                if (CurrentState == PlayerState.Loaded) {
+                    OnEventChanged (PlayerEvent.StartOfStream);
+                }
+                OnStateChanged (PlayerState.Playing);
+                return;
+            } else if (CurrentState == PlayerState.Playing && old_state == GstState.Playing && new_state == GstState.Paused) {
+                OnStateChanged (PlayerState.Paused);
+                return;
+            }
+        }
+        
         private void OnError (IntPtr player, uint domain, int code, IntPtr error, IntPtr debug)
         {
             Close (true);

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	Sun May  4 21:42:09 2008
@@ -282,10 +282,7 @@
         
         public virtual StreamPlaybackError PlaybackError {
             get { return playback_error; }
-            set { 
-                playback_error = value;
-                CanPlay &= value == StreamPlaybackError.None;
-            }
+            set { playback_error = value; }
         }
 
         private bool can_save_to_database = true;
@@ -302,7 +299,7 @@
 
         private bool can_play = true;
         public bool CanPlay {
-            get { return can_play; }
+            get { return can_play && PlaybackError == StreamPlaybackError.None; }
             set { can_play = value; }
         }
 

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	Sun May  4 21:42:09 2008
@@ -38,7 +38,9 @@
 using Banshee.Database;
 using Banshee.Sources;
 using Banshee.ServiceStack;
+using Banshee.Streaming;
 
+        using System.Diagnostics;
 // Disabling "is never used" warnings here because there are a lot
 // of properties/fields that are set via reflection at the database
 // layer - that is, they really are used, but the compiler doesn't
@@ -391,6 +393,20 @@
             get { return date_updated; }
             set { date_updated = value; }
         }
+        
+        [DatabaseColumn ("LastStreamError")]
+        private StreamPlaybackError playback_error;
+        public override StreamPlaybackError PlaybackError {
+            get { return playback_error; }
+            set {
+                if (playback_error == value) {
+                    return;
+                }
+                
+                playback_error = value; 
+                Save ();
+            }
+        }
 
         private long cache_entry_id;
         public long CacheEntryId {

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	Sun May  4 21:42:09 2008
@@ -42,10 +42,18 @@
 using Banshee.Collection.Database;
 using Banshee.Streaming;
 
+// MIGRATION NOTE: Return true if the step should allow the driver to continue
+//                 Return false if the step should terminate driver
+
 namespace Banshee.Database
 {
     public class BansheeDbFormatMigrator
     {
+        // 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 = 9;
+        protected const int CURRENT_METADATA_VERSION = 1;
         
 #region Migration Driver
         
@@ -57,13 +65,7 @@
 
         public event EventHandler Started;
         public event EventHandler Finished;
-        
-        // 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 = 8;
-        protected const int CURRENT_METADATA_VERSION = 1;
-        
+                
         protected class DatabaseVersionAttribute : Attribute 
         {
             private int version;
@@ -128,19 +130,22 @@
         public void Migrate ()
         {
             try {
+                
                 if (DatabaseVersion < CURRENT_VERSION) {
                     Execute ("BEGIN");
                     InnerMigrate ();
                     Execute ("COMMIT");
+                } else {
+                    Log.DebugFormat ("Database version {0} is up to date", DatabaseVersion);
                 }
-
+                
                 // Trigger metadata refreshes if necessary
                 int metadata_version = connection.Query<int> ("SELECT Value FROM CoreConfiguration WHERE Key = 'MetadataVersion'");
                 if (DatabaseVersion == CURRENT_VERSION && metadata_version < CURRENT_METADATA_VERSION) {
                     ServiceManager.ServiceStarted += OnServiceStarted;
                 }
             } catch (Exception) {
-                Log.Warning ("Rolling back migration");
+                Log.Warning ("Rolling back database migration");
                 Execute ("ROLLBACK");
                 throw;
             }
@@ -206,11 +211,10 @@
         
 #endregion
         
-#region Migration Step Implementations
 #pragma warning disable 0169
-        // NOTE: Return true if the step should allow the driver to continue
-        //       Return false if the step should terminate driver
-        
+
+#region Version 1
+                                
         [DatabaseVersion (1)]
         private bool Migrate_1 ()
         {
@@ -241,6 +245,10 @@
             }
         }
         
+#endregion
+
+#region Version 2
+        
         [DatabaseVersion (2)]
         private bool Migrate_2 ()
         {
@@ -249,6 +257,10 @@
             return true;
         }
 
+#endregion
+
+#region Version 3
+
         [DatabaseVersion (3)]
         private bool Migrate_3 ()
         {
@@ -260,12 +272,20 @@
             return true;
         }
 
+#endregion
+
+#region Version 4
+
         [DatabaseVersion (4)]
         private bool Migrate_4 ()
         {
             Execute ("ALTER TABLE CoreTracks ADD COLUMN LastSkippedStamp INTEGER");
             return true;
         }
+
+#endregion
+
+#region Version 5
         
         [DatabaseVersion (5)]
         private bool Migrate_5 ()
@@ -306,12 +326,20 @@
             return true;
         }
 
+#endregion
+
+#region Version 6
+
         [DatabaseVersion (6)]
         private bool Migrate_6 ()
         {
             Execute ("INSERT INTO CoreConfiguration VALUES (null, 'MetadataVersion', 0)");
             return true;
         }
+        
+#endregion
+
+#region Version 7
 
         [DatabaseVersion (7)]
         private bool Migrate_7 ()
@@ -322,6 +350,10 @@
             Execute ("DELETE FROM CoreCache; DELETE FROM CoreCacheModels");
             return true;
         }
+        
+#endregion
+
+#region Version 8
 
         [DatabaseVersion (8)]
         private bool Migrate_8 ()
@@ -334,11 +366,26 @@
             Application.ClientStarted += ReloadAllSources;
             return true;
         }
+        
+#endregion
+
+#region Version 9
+
+        [DatabaseVersion (9)]
+        private bool Migrate_9 ()
+        {
+            Execute (String.Format ("ALTER TABLE CoreTracks ADD COLUMN LastStreamError INTEGER DEFAULT {0}",
+                (int)StreamPlaybackError.None));
+            return true;
+        }
 
+#endregion
 
 #pragma warning restore 0169
         
-        private void InitializeFreshDatabase()
+#region Fresh database setup
+        
+        private void InitializeFreshDatabase ()
         {
             Execute("DROP TABLE IF EXISTS CoreConfiguration");
             Execute("DROP TABLE IF EXISTS CoreTracks");
@@ -389,6 +436,7 @@
                     MimeType            TEXT,
                     FileSize            INTEGER,
                     Attributes          INTEGER DEFAULT {0},
+                    LastStreamError     INTEGER DEFAULT {1},
                     
                     Title               TEXT,
                     TitleLowered        TEXT,
@@ -411,7 +459,7 @@
                     DateAddedStamp      INTEGER,
                     DateUpdatedStamp    INTEGER
                 )
-            ", (int)TrackMediaAttributes.Default));
+            ", (int)TrackMediaAttributes.Default, (int)StreamPlaybackError.None));
             Execute("CREATE INDEX CoreTracksPrimarySourceIndex ON CoreTracks(ArtistID, AlbumID, PrimarySourceID, Disc, TrackNumber, Uri)");
             Execute("CREATE INDEX CoreTracksAggregatesIndex ON CoreTracks(FileSize, Duration)");
             
@@ -519,9 +567,12 @@
             //Execute("CREATE INDEX CoreCacheModelId      ON CoreCache(ModelID)");
         }
         
+#endregion
+
+#region Legacy database migration
+        
         private void MigrateFromLegacyBanshee()
         {
-            Thread.Sleep (3000);
             Execute(@"
                 INSERT INTO CoreArtists 
                     SELECT DISTINCT null, 0, null, Artist, NULL, 0 
@@ -561,6 +612,7 @@
                         MimeType,
                         0,
                         {0},
+                        {1},
                         Title, NULL,
                         TrackNumber,
                         TrackCount,
@@ -577,7 +629,7 @@
                         DateAddedStamp,
                         DateAddedStamp
                         FROM Tracks
-            ", (int)TrackMediaAttributes.Default));
+            ", (int)TrackMediaAttributes.Default, (int)StreamPlaybackError.None));
 
             Execute ("update coretracks set lastplayedstamp = NULL where lastplayedstamp = -62135575200");
 
@@ -600,6 +652,10 @@
             Execute ("UPDATE CorePlaylists SET PrimarySourceID = 1");
         }
 
+#endregion
+
+#region Utilities / Source / Service Stuff
+
         private void OnServiceStarted (ServiceStartedArgs args)
         {
             if (args.Service is UserJobManager) {
@@ -619,6 +675,20 @@
                 RefreshMetadataDelayed ();
             }
         }
+        
+        private void ReloadAllSources (Client client)
+        {
+            Application.ClientStarted -= ReloadAllSources;
+            foreach (Source source in ServiceManager.SourceManager.Sources) {
+                if (source is ITrackModelSource) {
+                    ((ITrackModelSource)source).Reload ();
+                }
+            }
+        }
+        
+#endregion
+        
+#region Metadata Refresh Driver
 
         private void RefreshMetadataDelayed ()
         {
@@ -690,16 +760,6 @@
             job.Finish ();
             ServiceManager.SourceManager.MusicLibrary.NotifyTracksChanged ();
         }
-
-        private void ReloadAllSources (Client client)
-        {
-            Application.ClientStarted -= ReloadAllSources;
-            foreach (Source source in ServiceManager.SourceManager.Sources) {
-                if (source is ITrackModelSource) {
-                    ((ITrackModelSource)source).Reload ();
-                }
-            }
-        }
         
 #endregion
 

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.MediaEngine/NullPlayerEngine.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.MediaEngine/NullPlayerEngine.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.MediaEngine/NullPlayerEngine.cs	Sun May  4 21:42:09 2008
@@ -39,6 +39,16 @@
         {
         }
         
+        public override void Play ()
+        {
+            OnStateChanged (PlayerState.Playing);
+        }
+
+        public override void Pause ()
+        {
+            OnStateChanged (PlayerState.Paused);
+        }
+        
         private ushort volume;
         public override ushort Volume {
             get { return volume; }

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngine.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngine.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngine.cs	Sun May  4 21:42:09 2008
@@ -49,7 +49,9 @@
         private SafeUri current_uri;
         private PlayerState current_state = PlayerState.NotReady;
         private PlayerState last_state = PlayerState.NotReady;
-        private PlayerState idle_state = PlayerState.NotReady;
+        
+        // will be changed to PlayerState.Idle after going to PlayerState.Ready
+        private PlayerState idle_state = PlayerState.NotReady; 
         
         protected abstract void OpenUri (SafeUri uri);
         
@@ -93,24 +95,17 @@
             }
         
             try {
+                OnStateChanged (PlayerState.Loading);
                 OpenUri (uri);
-                OnEventChanged (PlayerEvent.StartOfStream);
-                OnStateChanged (PlayerState.Loaded);
             } catch (Exception e) {
-                Log.Exception (e);
+                Close (true);
                 OnEventChanged (new PlayerEventErrorArgs (e.Message));
             }
         }
         
-        public virtual void Play ()
-        {
-            OnStateChanged (PlayerState.Playing);
-        }
+        public abstract void Play ();
 
-        public virtual void Pause ()
-        {
-            OnStateChanged (PlayerState.Paused);
-        }
+        public abstract void Pause ();
         
         public virtual void VideoExpose (IntPtr window, bool direct)
         {
@@ -138,6 +133,8 @@
             last_state = current_state;
             current_state = state;
             
+            Log.DebugFormat ("Player state change: {0} -> {1}", last_state, current_state);
+            
             OnEventChanged (new PlayerEventStateChangeArgs (last_state, current_state));
             
             // Going to the Ready state automatically transitions to the Idle state

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngineService.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngineService.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngineService.cs	Sun May  4 21:42:09 2008
@@ -272,6 +272,7 @@
                 OpenCheck (track);
                 active_engine.Play ();
             } catch (Exception e) {
+                Log.Exception (e);
                 Log.Error (Catalog.GetString ("Problem with Player Engine"), e.Message, true);
                 Close ();
                 ActiveEngine = default_engine;
@@ -418,7 +419,9 @@
         
         public bool IsPlaying ()
         {
-            return CurrentState != PlayerState.Idle && CurrentState != PlayerState.NotReady;
+            return CurrentState == PlayerState.Playing || 
+                CurrentState == PlayerState.Paused || 
+                CurrentState == PlayerState.Loaded;
         }
 
         private void CheckPending ()

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEvent.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEvent.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEvent.cs	Sun May  4 21:42:09 2008
@@ -117,6 +117,7 @@
         Ready,
         Idle,
         Contacting,
+        Loading,
         Loaded,
         Playing,
         Paused

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.PlaybackController/PlaybackControllerService.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.PlaybackController/PlaybackControllerService.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.PlaybackController/PlaybackControllerService.cs	Sun May  4 21:42:09 2008
@@ -54,8 +54,8 @@
         private TrackInfo changing_to_track;
         private bool raise_started_after_transition = false;
         private bool transition_track_started = false;
-        
-        //private Random random = new Random ();
+        private int consecutive_errors;
+        private uint error_transition_id;
     
         private PlaybackShuffleMode shuffle_mode;
         private PlaybackRepeatMode repeat_mode;
@@ -83,7 +83,12 @@
             
             player_engine = ServiceManager.PlayerEngine;
             player_engine.PlayWhenIdleRequest += OnPlayerEnginePlayWhenIdleRequest;
-            player_engine.ConnectEvent (OnPlayerEvent, PlayerEvent.EndOfStream | PlayerEvent.StartOfStream, true);
+            player_engine.ConnectEvent (OnPlayerEvent, 
+                PlayerEvent.EndOfStream | 
+                PlayerEvent.StartOfStream |
+                PlayerEvent.StateChange |
+                PlayerEvent.Error, 
+                true);
         }
         
         protected virtual void InstantiateStacks ()
@@ -100,20 +105,28 @@
         private void OnPlayerEvent (PlayerEventArgs args)
         {
             switch (args.Event) {
+                case PlayerEvent.StartOfStream:
+                    consecutive_errors = 0;
+                    break;
                 case PlayerEvent.EndOfStream:
-                    if (!StopWhenFinished) {
-                        if (RepeatMode == PlaybackRepeatMode.RepeatSingle) {
-                            QueuePlayTrack ();
-                        } else {
-                            Next ();
-                        }
-                    } else {
+                    EosTransition ();
+                       break;
+                case PlayerEvent.Error:
+                    if (++consecutive_errors >= 20) {
+                        consecutive_errors = 0;
+                        player_engine.Close (false);
                         OnStopped ();
+                        break;
                     }
                     
-                    StopWhenFinished = false;
+                    CancelErrorTransition ();
+                    Application.RunTimeout (500, EosTransition);
                     break;
-                case PlayerEvent.StartOfStream:
+                case PlayerEvent.StateChange:
+                    if (((PlayerEventStateChangeArgs)args).Current != PlayerState.Loading) {
+                        break;
+                    }
+                       
                     TrackInfo track = player_engine.CurrentTrack;
                     if (changing_to_track != track && track != null) {
                         CurrentTrack = track;
@@ -131,9 +144,36 @@
             }       
         }
         
+        private void CancelErrorTransition ()
+        {
+            if (error_transition_id > 0) {
+                Application.IdleTimeoutRemove (error_transition_id);
+                error_transition_id = 0;
+            }
+        }
+        
+        private bool EosTransition ()
+        {
+            if (!StopWhenFinished) {
+                if (RepeatMode == PlaybackRepeatMode.RepeatSingle) {
+                    QueuePlayTrack ();
+                } else {
+                    Next ();
+                }
+            } else {
+                OnStopped ();
+            }
+            
+            StopWhenFinished = false;
+            return false;
+        }
+        
         public void First ()
         {
+            CancelErrorTransition ();
+            
             Source = NextSource;
+            
             // This and OnTransition() below commented out b/c of BGO #524556
             //raise_started_after_transition = true;
             
@@ -153,6 +193,8 @@
         
         public void Next (bool restart)
         {
+            CancelErrorTransition ();
+            
             Source = NextSource;
             raise_started_after_transition = true;
 
@@ -174,6 +216,8 @@
         
         public void Previous (bool restart)
         {
+            CancelErrorTransition ();
+            
             Source = NextSource;
             raise_started_after_transition = true;
 

Modified: trunk/banshee/src/Core/Banshee.Services/Makefile.am
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Makefile.am	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Makefile.am	Sun May  4 21:42:09 2008
@@ -3,167 +3,167 @@
 LINK = $(REF_BANSHEE_SERVICES)
 
 SOURCES =  \
-	Banshee.Base/RateLimiter.cs \
-	Banshee.Base/ThreadAssist.cs \
-	Banshee.Collection.Database/CachedList.cs \
-	Banshee.Collection.Database/DatabaseAlbumInfo.cs \
-	Banshee.Collection.Database/DatabaseAlbumListModel.cs \
-	Banshee.Collection.Database/DatabaseArtistInfo.cs \
-	Banshee.Collection.Database/DatabaseArtistListModel.cs \
-	Banshee.Collection.Database/DatabaseImportManager.cs \
-	Banshee.Collection.Database/DatabaseTrackInfo.cs \
-	Banshee.Collection.Database/DatabaseTrackListModel.cs \
-	Banshee.Collection.Database/DatabaseTrackModelCache.cs \
-	Banshee.Collection.Database/DatabaseTrackModelProvider.cs \
-	Banshee.Collection.Database/IDatabaseTrackModelCache.cs \
-	Banshee.Collection.Database/IDatabaseTrackModelProvider.cs \
-	Banshee.Collection/AlbumListModel.cs \
-	Banshee.Collection/ArtistListModel.cs \
-	Banshee.Collection/BansheeListModel.cs \
-	Banshee.Collection/ExportableModel.cs \
-	Banshee.Collection/IExportableModel.cs \
-	Banshee.Collection/IHasTrackSelection.cs \
-	Banshee.Collection/ImportEventHandler.cs \
-	Banshee.Collection/ImportManager.cs \
-	Banshee.Collection/MemoryTrackListModel.cs \
-	Banshee.Collection/ModelHelper.cs \
-	Banshee.Collection/SelectAllSelection.cs \
-	Banshee.Collection/TrackListModel.cs \
-	Banshee.Configuration/DatabaseConfigurationClient.cs \
-	Banshee.Database/BansheeDbConnection.cs \
-	Banshee.Database/BansheeDbFormatMigrator.cs \
-	Banshee.Database/BansheeModelCache.cs \
-	Banshee.Database/BansheeModelProvider.cs \
-	Banshee.Equalizer/EqualizerManager.cs \
-	Banshee.Equalizer/EqualizerSetting.cs \
-	Banshee.Equalizer/EqualizerSettingEvent.cs \
-	Banshee.Hardware/HardwareManager.cs \
-	Banshee.Hardware/IBlockDevice.cs \
-	Banshee.Hardware/ICdromDevice.cs \
-	Banshee.Hardware/ICustomDeviceProvider.cs \
-	Banshee.Hardware/IDevice.cs \
-	Banshee.Hardware/IDeviceMediaCapabilities.cs \
-	Banshee.Hardware/IDiscVolume.cs \
-	Banshee.Hardware/IDiskDevice.cs \
-	Banshee.Hardware/IHardwareManager.cs \
-	Banshee.Hardware/IVolume.cs \
-	Banshee.Library/HomeDirectoryImportSource.cs \
-	Banshee.Library/IImportSource.cs \
-	Banshee.Library/ImportSourceManager.cs \
-	Banshee.Library/LibraryImportManager.cs \
-	Banshee.Library/LibraryLocationPreference.cs \
-	Banshee.Library/LibrarySource.cs \
-	Banshee.Library/MusicLibrarySource.cs \
-	Banshee.Library/ThreadPoolImportSource.cs \
-	Banshee.Library/VideoLibrarySource.cs \
-	Banshee.MediaEngine/IAudioCdRipper.cs \
-	Banshee.MediaEngine/IEqualizer.cs \
-	Banshee.MediaEngine/IPlayerEngineService.cs \
-	Banshee.MediaEngine/ITranscoder.cs \
-	Banshee.MediaEngine/NullPlayerEngine.cs \
-	Banshee.MediaEngine/PlayerEngine.cs \
-	Banshee.MediaEngine/PlayerEvent.cs \
-	Banshee.MediaEngine/PlayerEngineService.cs \
-	Banshee.MediaEngine/TranscoderService.cs \
-	Banshee.MediaProfiles/MediaProfileManager.cs \
-	Banshee.MediaProfiles/Pipeline.cs \
-	Banshee.MediaProfiles/PipelineVariable.cs \
-	Banshee.MediaProfiles/Profile.cs \
-	Banshee.MediaProfiles/ProfileConfiguration.cs \
-	Banshee.Metadata.Embedded/EmbeddedMetadataProvider.cs \
-	Banshee.Metadata.Embedded/EmbeddedQueryJob.cs \
-	Banshee.Metadata.MusicBrainz/MusicBrainzMetadataProvider.cs \
-	Banshee.Metadata.MusicBrainz/MusicBrainzQueryJob.cs \
-	Banshee.Metadata.Rhapsody/RhapsodyMetadataProvider.cs \
-	Banshee.Metadata.Rhapsody/RhapsodyQueryJob.cs \
-	Banshee.Metadata/BaseMetadataProvider.cs \
-	Banshee.Metadata/IMetadataLookupJob.cs \
-	Banshee.Metadata/IMetadataProvider.cs \
-	Banshee.Metadata/MetadataService.cs \
-	Banshee.Metadata/MetadataServiceJob.cs \
-	Banshee.Metadata/MetadataSettings.cs \
-	Banshee.Networking/NetworkDetect.cs \
-	Banshee.Networking/NetworkManager.cs \
-	Banshee.PlaybackController/IBasicPlaybackController.cs \
-	Banshee.PlaybackController/ICanonicalPlaybackController.cs \
-	Banshee.PlaybackController/IPlaybackController.cs \
-	Banshee.PlaybackController/IPlaybackControllerExportable.cs \
-	Banshee.PlaybackController/PlaybackControllerDatabaseStack.cs \
-	Banshee.PlaybackController/PlaybackControllerService.cs \
-	Banshee.PlaybackController/PlaybackRepeatMode.cs \
-	Banshee.PlaybackController/PlaybackShuffleMode.cs \
-	Banshee.PlayerMigration/AmarokPlayerImportSource.cs \
-	Banshee.Playlist/AbstractPlaylistSource.cs \
-	Banshee.Playlist/PlaylistFileUtil.cs \
-	Banshee.Playlist/PlaylistSource.cs \
-	Banshee.Playlists.Formats/AsxPlaylistFormat.cs \
-	Banshee.Playlists.Formats/InvalidPlaylistException.cs \
-	Banshee.Playlists.Formats/IPlaylistFormat.cs \
-	Banshee.Playlists.Formats/M3uPlaylistFormat.cs \
-	Banshee.Playlists.Formats/PlaylistFormatBase.cs \
-	Banshee.Playlists.Formats/PlaylistFormatDescription.cs \
-	Banshee.Playlists.Formats/PlaylistParser.cs \
-	Banshee.Playlists.Formats/PlsPlaylistFormat.cs \
-	Banshee.Preferences/Collection.cs \
-	Banshee.Preferences/Page.cs \
-	Banshee.Preferences/Preference.cs \
-	Banshee.Preferences/PreferenceBase.cs \
-	Banshee.Preferences/PreferenceService.cs \
-	Banshee.Preferences/Root.cs \
-	Banshee.Preferences/SchemaPreference.cs \
-	Banshee.Preferences/Section.cs \
-	Banshee.Preferences/VoidPreference.cs \
-	Banshee.Query/AbstractPlaylistQueryValue.cs \
-	Banshee.Query/BansheeQuery.cs \
-	Banshee.Query/NaturalIntegerQueryValue.cs \
-	Banshee.Query/PlaylistQueryValue.cs \
-	Banshee.Query/RatingQueryValue.cs \
-	Banshee.Query/SmartPlaylistQueryValue.cs \
-	Banshee.Query/YearQueryValue.cs \
-	Banshee.ServiceStack/Application.cs \
-	Banshee.ServiceStack/BatchUserJob.cs \
-	Banshee.ServiceStack/Client.cs \
-	Banshee.ServiceStack/DBusServiceManager.cs \
-	Banshee.ServiceStack/IDBusExportable.cs \
-	Banshee.ServiceStack/IDelayedInitializeService.cs \
-	Banshee.ServiceStack/IExtensionService.cs \
-	Banshee.ServiceStack/IInitializeService.cs \
-	Banshee.ServiceStack/InterfaceAction.cs \
-	Banshee.ServiceStack/IRequiredService.cs \
-	Banshee.ServiceStack/IService.cs \
-	Banshee.ServiceStack/IUserJob.cs \
-	Banshee.ServiceStack/ServiceManager.cs \
-	Banshee.ServiceStack/ServiceStartedHandler.cs \
-	Banshee.ServiceStack/TestUserJob.cs \
-	Banshee.ServiceStack/UserJob.cs \
-	Banshee.ServiceStack/UserJobEventHandler.cs \
-	Banshee.ServiceStack/UserJobManager.cs \
-	Banshee.SmartPlaylist/Migrator.cs \
-	Banshee.SmartPlaylist/SmartPlaylistDefinition.cs \
-	Banshee.SmartPlaylist/SmartPlaylistSource.cs \
-	Banshee.Sources/DatabaseSource.cs \
-	Banshee.Sources/DurationStatusFormatters.cs \
-	Banshee.Sources/ErrorSource.cs \
-	Banshee.Sources/IDiskUsageReporter.cs \
-	Banshee.Sources/IDurationAggregator.cs \
-	Banshee.Sources/IFileSizeAggregator.cs \
-	Banshee.Sources/IImportable.cs \
-	Banshee.Sources/ISource.cs \
-	Banshee.Sources/ISourceManager.cs \
-	Banshee.Sources/ITrackModelSource.cs \
-	Banshee.Sources/IUnmapableSource.cs \
-	Banshee.Sources/MessageAction.cs \
-	Banshee.Sources/PrimarySource.cs \
-	Banshee.Sources/Source.cs \
-	Banshee.Sources/SourceManager.cs \
-	Banshee.Sources/SourceMergeType.cs \
-	Banshee.Sources/SourceMessage.cs \
-	Banshee.Streaming/RadioTrackInfo.cs \
-	Banshee.Web/Browser.cs
+    Banshee.Base/RateLimiter.cs \
+    Banshee.Base/ThreadAssist.cs \
+    Banshee.Collection.Database/CachedList.cs \
+    Banshee.Collection.Database/DatabaseAlbumInfo.cs \
+    Banshee.Collection.Database/DatabaseAlbumListModel.cs \
+    Banshee.Collection.Database/DatabaseArtistInfo.cs \
+    Banshee.Collection.Database/DatabaseArtistListModel.cs \
+    Banshee.Collection.Database/DatabaseImportManager.cs \
+    Banshee.Collection.Database/DatabaseTrackInfo.cs \
+    Banshee.Collection.Database/DatabaseTrackListModel.cs \
+    Banshee.Collection.Database/DatabaseTrackModelCache.cs \
+    Banshee.Collection.Database/DatabaseTrackModelProvider.cs \
+    Banshee.Collection.Database/IDatabaseTrackModelCache.cs \
+    Banshee.Collection.Database/IDatabaseTrackModelProvider.cs \
+    Banshee.Collection/AlbumListModel.cs \
+    Banshee.Collection/ArtistListModel.cs \
+    Banshee.Collection/BansheeListModel.cs \
+    Banshee.Collection/ExportableModel.cs \
+    Banshee.Collection/IExportableModel.cs \
+    Banshee.Collection/IHasTrackSelection.cs \
+    Banshee.Collection/ImportEventHandler.cs \
+    Banshee.Collection/ImportManager.cs \
+    Banshee.Collection/MemoryTrackListModel.cs \
+    Banshee.Collection/ModelHelper.cs \
+    Banshee.Collection/SelectAllSelection.cs \
+    Banshee.Collection/TrackListModel.cs \
+    Banshee.Configuration/DatabaseConfigurationClient.cs \
+    Banshee.Database/BansheeDbConnection.cs \
+    Banshee.Database/BansheeDbFormatMigrator.cs \
+    Banshee.Database/BansheeModelCache.cs \
+    Banshee.Database/BansheeModelProvider.cs \
+    Banshee.Equalizer/EqualizerManager.cs \
+    Banshee.Equalizer/EqualizerSetting.cs \
+    Banshee.Equalizer/EqualizerSettingEvent.cs \
+    Banshee.Hardware/HardwareManager.cs \
+    Banshee.Hardware/IBlockDevice.cs \
+    Banshee.Hardware/ICdromDevice.cs \
+    Banshee.Hardware/ICustomDeviceProvider.cs \
+    Banshee.Hardware/IDevice.cs \
+    Banshee.Hardware/IDeviceMediaCapabilities.cs \
+    Banshee.Hardware/IDiscVolume.cs \
+    Banshee.Hardware/IDiskDevice.cs \
+    Banshee.Hardware/IHardwareManager.cs \
+    Banshee.Hardware/IVolume.cs \
+    Banshee.Library/HomeDirectoryImportSource.cs \
+    Banshee.Library/IImportSource.cs \
+    Banshee.Library/ImportSourceManager.cs \
+    Banshee.Library/LibraryImportManager.cs \
+    Banshee.Library/LibraryLocationPreference.cs \
+    Banshee.Library/LibrarySource.cs \
+    Banshee.Library/MusicLibrarySource.cs \
+    Banshee.Library/ThreadPoolImportSource.cs \
+    Banshee.Library/VideoLibrarySource.cs \
+    Banshee.MediaEngine/IAudioCdRipper.cs \
+    Banshee.MediaEngine/IEqualizer.cs \
+    Banshee.MediaEngine/IPlayerEngineService.cs \
+    Banshee.MediaEngine/ITranscoder.cs \
+    Banshee.MediaEngine/NullPlayerEngine.cs \
+    Banshee.MediaEngine/PlayerEngine.cs \
+    Banshee.MediaEngine/PlayerEngineService.cs \
+    Banshee.MediaEngine/PlayerEvent.cs \
+    Banshee.MediaEngine/TranscoderService.cs \
+    Banshee.MediaProfiles/MediaProfileManager.cs \
+    Banshee.MediaProfiles/Pipeline.cs \
+    Banshee.MediaProfiles/PipelineVariable.cs \
+    Banshee.MediaProfiles/Profile.cs \
+    Banshee.MediaProfiles/ProfileConfiguration.cs \
+    Banshee.Metadata.Embedded/EmbeddedMetadataProvider.cs \
+    Banshee.Metadata.Embedded/EmbeddedQueryJob.cs \
+    Banshee.Metadata.MusicBrainz/MusicBrainzMetadataProvider.cs \
+    Banshee.Metadata.MusicBrainz/MusicBrainzQueryJob.cs \
+    Banshee.Metadata.Rhapsody/RhapsodyMetadataProvider.cs \
+    Banshee.Metadata.Rhapsody/RhapsodyQueryJob.cs \
+    Banshee.Metadata/BaseMetadataProvider.cs \
+    Banshee.Metadata/IMetadataLookupJob.cs \
+    Banshee.Metadata/IMetadataProvider.cs \
+    Banshee.Metadata/MetadataService.cs \
+    Banshee.Metadata/MetadataServiceJob.cs \
+    Banshee.Metadata/MetadataSettings.cs \
+    Banshee.Networking/NetworkDetect.cs \
+    Banshee.Networking/NetworkManager.cs \
+    Banshee.PlaybackController/IBasicPlaybackController.cs \
+    Banshee.PlaybackController/ICanonicalPlaybackController.cs \
+    Banshee.PlaybackController/IPlaybackController.cs \
+    Banshee.PlaybackController/IPlaybackControllerExportable.cs \
+    Banshee.PlaybackController/PlaybackControllerDatabaseStack.cs \
+    Banshee.PlaybackController/PlaybackControllerService.cs \
+    Banshee.PlaybackController/PlaybackRepeatMode.cs \
+    Banshee.PlaybackController/PlaybackShuffleMode.cs \
+    Banshee.PlayerMigration/AmarokPlayerImportSource.cs \
+    Banshee.Playlist/AbstractPlaylistSource.cs \
+    Banshee.Playlist/PlaylistFileUtil.cs \
+    Banshee.Playlist/PlaylistSource.cs \
+    Banshee.Playlists.Formats/AsxPlaylistFormat.cs \
+    Banshee.Playlists.Formats/InvalidPlaylistException.cs \
+    Banshee.Playlists.Formats/IPlaylistFormat.cs \
+    Banshee.Playlists.Formats/M3uPlaylistFormat.cs \
+    Banshee.Playlists.Formats/PlaylistFormatBase.cs \
+    Banshee.Playlists.Formats/PlaylistFormatDescription.cs \
+    Banshee.Playlists.Formats/PlaylistParser.cs \
+    Banshee.Playlists.Formats/PlsPlaylistFormat.cs \
+    Banshee.Preferences/Collection.cs \
+    Banshee.Preferences/Page.cs \
+    Banshee.Preferences/Preference.cs \
+    Banshee.Preferences/PreferenceBase.cs \
+    Banshee.Preferences/PreferenceService.cs \
+    Banshee.Preferences/Root.cs \
+    Banshee.Preferences/SchemaPreference.cs \
+    Banshee.Preferences/Section.cs \
+    Banshee.Preferences/VoidPreference.cs \
+    Banshee.Query/AbstractPlaylistQueryValue.cs \
+    Banshee.Query/BansheeQuery.cs \
+    Banshee.Query/NaturalIntegerQueryValue.cs \
+    Banshee.Query/PlaylistQueryValue.cs \
+    Banshee.Query/RatingQueryValue.cs \
+    Banshee.Query/SmartPlaylistQueryValue.cs \
+    Banshee.Query/YearQueryValue.cs \
+    Banshee.ServiceStack/Application.cs \
+    Banshee.ServiceStack/BatchUserJob.cs \
+    Banshee.ServiceStack/Client.cs \
+    Banshee.ServiceStack/DBusServiceManager.cs \
+    Banshee.ServiceStack/IDBusExportable.cs \
+    Banshee.ServiceStack/IDelayedInitializeService.cs \
+    Banshee.ServiceStack/IExtensionService.cs \
+    Banshee.ServiceStack/IInitializeService.cs \
+    Banshee.ServiceStack/InterfaceAction.cs \
+    Banshee.ServiceStack/IRequiredService.cs \
+    Banshee.ServiceStack/IService.cs \
+    Banshee.ServiceStack/IUserJob.cs \
+    Banshee.ServiceStack/ServiceManager.cs \
+    Banshee.ServiceStack/ServiceStartedHandler.cs \
+    Banshee.ServiceStack/TestUserJob.cs \
+    Banshee.ServiceStack/UserJob.cs \
+    Banshee.ServiceStack/UserJobEventHandler.cs \
+    Banshee.ServiceStack/UserJobManager.cs \
+    Banshee.SmartPlaylist/Migrator.cs \
+    Banshee.SmartPlaylist/SmartPlaylistDefinition.cs \
+    Banshee.SmartPlaylist/SmartPlaylistSource.cs \
+    Banshee.Sources/DatabaseSource.cs \
+    Banshee.Sources/DurationStatusFormatters.cs \
+    Banshee.Sources/ErrorSource.cs \
+    Banshee.Sources/IDiskUsageReporter.cs \
+    Banshee.Sources/IDurationAggregator.cs \
+    Banshee.Sources/IFileSizeAggregator.cs \
+    Banshee.Sources/IImportable.cs \
+    Banshee.Sources/ISource.cs \
+    Banshee.Sources/ISourceManager.cs \
+    Banshee.Sources/ITrackModelSource.cs \
+    Banshee.Sources/IUnmapableSource.cs \
+    Banshee.Sources/MessageAction.cs \
+    Banshee.Sources/PrimarySource.cs \
+    Banshee.Sources/Source.cs \
+    Banshee.Sources/SourceManager.cs \
+    Banshee.Sources/SourceMergeType.cs \
+    Banshee.Sources/SourceMessage.cs \
+    Banshee.Streaming/RadioTrackInfo.cs \
+    Banshee.Web/Browser.cs
 
 RESOURCES =  \
-	Banshee.Services.addin.xml \
-	Banshee.Services.addins
+    Banshee.Services.addin.xml \
+    Banshee.Services.addins
 
 module_DATA = Banshee.Services.addins
 

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/ColumnCellPlaybackIndicator.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/ColumnCellPlaybackIndicator.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/ColumnCellPlaybackIndicator.cs	Sun May  4 21:42:09 2008
@@ -33,6 +33,7 @@
 using Hyena.Data.Gui;
 using Banshee.Gui;
 
+using Banshee.Streaming;
 using Banshee.MediaEngine;
 using Banshee.ServiceStack;
 
@@ -40,51 +41,66 @@
 {
     public class ColumnCellPlaybackIndicator : ColumnCell
     {
-        private const int pixbuf_size = 16;
-        private const int pixbuf_spacing = 4;
+        private enum Icon : int {
+            Playing,
+            Paused,
+            Error,
+            Protected
+        }
         
-        private Gdk.Pixbuf pixbuf;
-        private Gdk.Pixbuf pixbuf_paused;
+        private const int pixbuf_size = 16;
+        private const int pixbuf_spacing = 4;        
+        private Gdk.Pixbuf [] pixbufs = new Gdk.Pixbuf[4];
         
         public ColumnCellPlaybackIndicator (string property) : base (property, true)
         {
-            LoadPixbuf ();
+            LoadPixbufs ();
         }
         
-        private void LoadPixbuf ()
+        private void LoadPixbufs ()
         {
-            if (pixbuf != null) {
-                pixbuf.Dispose ();
-                pixbuf = null;
-            }
-            
-            if (pixbuf_paused != null) {
-                pixbuf_paused.Dispose ();
-                pixbuf_paused = null;
+            for (int i = 0; i < pixbufs.Length; i++) {
+                if (pixbufs[i] != null) {
+                    pixbufs[i].Dispose ();
+                    pixbufs[i] = null;
+                }
             }
             
-            pixbuf = IconThemeUtils.LoadIcon (pixbuf_size, "media-playback-start");
-            pixbuf_paused = IconThemeUtils.LoadIcon (pixbuf_size, "media-playback-pause");
+            pixbufs[(int)Icon.Playing] = IconThemeUtils.LoadIcon (pixbuf_size, "media-playback-start");
+            pixbufs[(int)Icon.Paused] = IconThemeUtils.LoadIcon (pixbuf_size, "media-playback-pause");
+            pixbufs[(int)Icon.Error] = IconThemeUtils.LoadIcon (pixbuf_size, "emblem-unreadable", "dialog-error");
+            pixbufs[(int)Icon.Protected] = IconThemeUtils.LoadIcon (pixbuf_size, "emblem-readonly", "dialog-error");
         }
         
         public override void NotifyThemeChange ()
         {
-            LoadPixbuf ();
+            LoadPixbufs ();
         }
 
         public override void Render (CellContext context, StateType state, double cellWidth, double cellHeight)
         {
-            if (!ServiceManager.PlayerEngine.IsPlaying ((TrackInfo)BoundObject)) {
+            TrackInfo track = (TrackInfo)BoundObject;
+        
+            if (track.PlaybackError == StreamPlaybackError.None && !ServiceManager.PlayerEngine.IsPlaying (track)) {
                 return;
             }
             
-            Gdk.Pixbuf render_pixbuf = pixbuf;
-            if (ServiceManager.PlayerEngine.CurrentState == PlayerState.Paused) {
-                render_pixbuf = pixbuf_paused;
-            }
+            Icon icon;
+            
+            if (track.PlaybackError == StreamPlaybackError.None) {
+                icon = ServiceManager.PlayerEngine.CurrentState == PlayerState.Paused
+                    ? Icon.Paused
+                    : Icon.Playing;
+            } else if (track.PlaybackError == StreamPlaybackError.Drm) {
+                icon = Icon.Protected;
+            } else {
+                icon = Icon.Error;
+            } 
             
             context.Context.Translate (0, 0.5);
             
+            Gdk.Pixbuf render_pixbuf = pixbufs[(int)icon];
+            
             Cairo.Rectangle pixbuf_area = new Cairo.Rectangle (pixbuf_spacing, 
                 (cellHeight - render_pixbuf.Height) / 2, render_pixbuf.Width, render_pixbuf.Height);
             

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/TrackInfoDisplay.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/TrackInfoDisplay.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/TrackInfoDisplay.cs	Sun May  4 21:42:09 2008
@@ -417,9 +417,9 @@
         {
             if (args.Event == PlayerEvent.StartOfStream || args.Event == PlayerEvent.TrackInfoUpdated) {
                 LoadCurrentTrack ();
-            } else if (args.Event == PlayerEvent.StateChange) {
-                if ((incoming_track != null || incoming_pixbuf != null) || 
-                    ((PlayerEventStateChangeArgs)args).Current == PlayerState.Idle) {
+            } else if (args.Event == PlayerEvent.StateChange && (incoming_track != null || incoming_pixbuf != null)) {
+                PlayerEventStateChangeArgs state = (PlayerEventStateChangeArgs)args;
+                if (state.Current == PlayerState.Idle) {
                     if (idle_timeout_id > 0) {
                         GLib.Source.Remove (idle_timeout_id);
                     } else {



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