[banshee] [Podcasting] Show errors in the source status msg area



commit 2ddc42079a75e2c5c0fd6fce59baf345d46cccdd
Author: Gabriel Burt <gabriel burt gmail com>
Date:   Sat Aug 14 18:00:19 2010 -0700

    [Podcasting] Show errors in the source status msg area
    
    If a feed fails to update to get subscribed to properly, it will now
    appear in the status message area, with actions to remove or unsubscribe
    from the feed.  Fixes bgo#568733

 .../Banshee.Services/Banshee.Sources/Source.cs     |    4 +
 .../Banshee.Podcasting.Data/PodcastSource.cs       |  105 ++++++++++++++++++++
 .../Banshee.Podcasting.Gui/PodcastActions.cs       |    4 +-
 .../Banshee.Podcasting/ItmsPodcast.cs              |    7 +-
 .../Banshee.Podcasting/PodcastService.cs           |   36 +++++---
 src/Libraries/Migo/Migo.Syndication/Feed.cs        |    4 +-
 src/Libraries/Migo/Migo.Syndication/FeedManager.cs |   10 ++-
 .../Migo/Migo.Syndication/FeedUpdateTask.cs        |    6 +-
 8 files changed, 154 insertions(+), 22 deletions(-)
---
diff --git a/src/Core/Banshee.Services/Banshee.Sources/Source.cs b/src/Core/Banshee.Services/Banshee.Sources/Source.cs
index bdf7f68..a9cbee4 100644
--- a/src/Core/Banshee.Services/Banshee.Sources/Source.cs
+++ b/src/Core/Banshee.Services/Banshee.Sources/Source.cs
@@ -454,6 +454,10 @@ namespace Banshee.Sources
 
         private void HandleMessageUpdated (object o, EventArgs args)
         {
+            if (CurrentMessage == o && CurrentMessage.IsHidden) {
+                PopMessage ();
+            }
+
             OnMessageNotify ();
         }
 
diff --git a/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Data/PodcastSource.cs b/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Data/PodcastSource.cs
index 609fb05..9e67324 100644
--- a/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Data/PodcastSource.cs
+++ b/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Data/PodcastSource.cs
@@ -27,6 +27,7 @@
  */
 
 using System;
+using System.Linq;
 using System.Collections.Generic;
 
 using Gtk;
@@ -94,6 +95,110 @@ namespace Banshee.Podcasting.Gui
             get { return UniqueId; }
         }
 
+        class FeedMessage : SourceMessage
+        {
+            public Feed Feed { get; set; }
+
+            public bool Valid { get; private set; }
+
+            public FeedMessage (Source src, Feed feed) : base (src)
+            {
+                Feed = feed;
+                Update ();
+            }
+
+            public void Update ()
+            {
+                ClearActions ();
+                CanClose = Feed.LastDownloadError != FeedDownloadError.None;
+                IsSpinning = !CanClose;
+
+                var title = Feed.Title == Feed.UnknownPodcastTitle ? Feed.Url : Feed.Title;
+
+                if (CanClose) {
+                    Text = String.Format (GetErrorText (), title);
+                    SetIconName ("dialog-error");
+
+                    AddAction (new MessageAction (Catalog.GetString ("Remove Podcast"), delegate {
+                        Feed.Delete (true);
+                        IsHidden = true;
+                    }));
+
+                    AddAction (new MessageAction (Catalog.GetString ("Disable Auto Updates"), delegate {
+                        Feed.IsSubscribed = false;
+                        Feed.Save ();
+                        IsHidden = true;
+                    }));
+                } else {
+                    Text = String.Format (Catalog.GetString ("Loading {0}"), title);
+                }
+
+                // TODO Avoid nagging about an error more than once
+                Valid = true;//Feed.LastDownloadTime == DateTime.MinValue || Feed.LastDownloadTime > last_feed_nag;
+            }
+
+            private string GetErrorText ()
+            {
+                switch (Feed.LastDownloadError) {
+                    case FeedDownloadError.DoesNotExist:
+                    case FeedDownloadError.DownloadFailed:
+                        return Catalog.GetString ("Network error updating {0}");
+
+                    case FeedDownloadError.InvalidFeedFormat:
+                    case FeedDownloadError.NormalizationFailed:
+                    case FeedDownloadError.UnsupportedMsXml:
+                    case FeedDownloadError.UnsupportedDtd:
+                        return Catalog.GetString ("Parsing error updating {0}");
+
+                    case FeedDownloadError.UnsupportedAuth:
+                        return Catalog.GetString ("Authentication error updating {0}");
+
+                    default:
+                        return Catalog.GetString ("Error updating {0}");
+                }
+            }
+        }
+
+        //private static DateTime last_feed_nag = DateTime.MinValue;
+        private List<FeedMessage> feed_messages = new List<FeedMessage> ();
+        public void UpdateFeedMessages ()
+        {
+            Console.WriteLine ("Updating feed msgs");
+            var feeds = Feed.Provider.FetchAllMatching (
+                "IsSubscribed = 1 AND (LastDownloadTime = 0 OR LastDownloadError != 0) ORDER BY LastDownloadTime ASC").ToList ();
+
+            lock (feed_messages) {
+                var msgs = new List<FeedMessage> ();
+
+                var cur = CurrentMessage as FeedMessage;
+                if (cur != null && feeds.Contains (cur.Feed)) {
+                    cur.Update ();
+                    feeds.Remove (cur.Feed);
+                    feed_messages.Remove (cur);
+                    msgs.Add (cur);
+                }
+
+                feed_messages.ForEach (RemoveMessage);
+                feed_messages.Clear ();
+
+                foreach (var feed in feeds) {
+                    var msg = new FeedMessage (this, feed);
+                    if (msg.Valid) {
+                        msgs.Add (msg);
+                        PushMessage (msg);
+                    }
+                }
+
+                feed_messages = msgs;
+                //last_feed_nag = DateTime.Now;
+
+                // If there's at least one new message, notify the user
+                if (msgs.Count > ((cur != null) ? 1 : 0)) {
+                    NotifyUser ();
+                }
+            }
+        }
+
 #region Constructors
 
         public PodcastSource () : base (Catalog.GetString ("Podcasts"), "PodcastLibrary", 51)
diff --git a/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Gui/PodcastActions.cs b/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Gui/PodcastActions.cs
index acf159e..c96f233 100644
--- a/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Gui/PodcastActions.cs
+++ b/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Gui/PodcastActions.cs
@@ -445,7 +445,9 @@ namespace Banshee.Podcasting.Gui
         private void OnPodcastUpdateAll (object sender, EventArgs e)
         {
             foreach (Feed feed in Feed.Provider.FetchAll ()) {
-                feed.Update ();
+                if (feed.IsSubscribed) {
+                    feed.Update ();
+                }
             }
         }
 
diff --git a/src/Extensions/Banshee.Podcasting/Banshee.Podcasting/ItmsPodcast.cs b/src/Extensions/Banshee.Podcasting/Banshee.Podcasting/ItmsPodcast.cs
index 29a85a7..305cdba 100644
--- a/src/Extensions/Banshee.Podcasting/Banshee.Podcasting/ItmsPodcast.cs
+++ b/src/Extensions/Banshee.Podcasting/Banshee.Podcasting/ItmsPodcast.cs
@@ -45,14 +45,17 @@ namespace Banshee.Podcasting
 
             feed_url = GetString ("feedURL");
 
-            // <key>podcastName</key>
-            // <string>This Week in Django - MP3 Edition</string>
+            try {
+                Title = GetString ("podcastName");
+            } catch (Exception) {}
         }
 
         public string FeedUrl {
             get { return feed_url; }
         }
 
+        public string Title { get; private set; }
+
         private void Fetch (string url, int tries)
         {
             url = url.Replace ("itms://", "http://";);
diff --git a/src/Extensions/Banshee.Podcasting/Banshee.Podcasting/PodcastService.cs b/src/Extensions/Banshee.Podcasting/Banshee.Podcasting/PodcastService.cs
index 074a5c4..85e04ed 100644
--- a/src/Extensions/Banshee.Podcasting/Banshee.Podcasting/PodcastService.cs
+++ b/src/Extensions/Banshee.Podcasting/Banshee.Podcasting/PodcastService.cs
@@ -29,6 +29,7 @@
 //
 
 using System;
+using System.Linq;
 using System.IO;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
@@ -276,13 +277,13 @@ namespace Banshee.Podcasting
 
                 ServiceManager.Get<Network> ().StateChanged += OnNetworkStateChanged;
             });
+
+            source.UpdateFeedMessages ();
         }
 
         private void OnNetworkStateChanged (object o, NetworkStateChangedArgs args)
         {
-            if (args.Connected) {
-                RefreshFeeds ();
-            }
+            RefreshFeeds ();
         }
 
         bool disposing;
@@ -328,11 +329,14 @@ namespace Banshee.Podcasting
 
         private bool RefreshFeeds ()
         {
+            if (!ServiceManager.Get<Network> ().Connected)
+                return true;
+
             Hyena.Log.Debug ("Refreshing any podcasts that haven't been updated in over an hour");
             Banshee.Kernel.Scheduler.Schedule (new Banshee.Kernel.DelegateJob (delegate {
                 DateTime now = DateTime.Now;
                 foreach (Feed feed in Feed.Provider.FetchAll ()) {
-                    if ((now - feed.LastDownloadTime).TotalHours > 1) {
+                    if (feed.IsSubscribed && (now - feed.LastDownloadTime).TotalHours > 1) {
                         feed.Update ();
                         RefreshArtworkFor (feed);
                     }
@@ -347,8 +351,8 @@ namespace Banshee.Podcasting
                 return;
             }
 
-            // Handle OPML files
             if (uri.Contains ("opml") || uri.EndsWith (".miro") || uri.EndsWith (".democracy")) {
+                // Handle OPML files
                 try {
                     OpmlParser opml_parser = new OpmlParser (uri, true);
                     foreach (string feed in opml_parser.Feeds) {
@@ -358,23 +362,22 @@ namespace Banshee.Podcasting
                     Log.Exception (e);
                 }
             } else if (uri.Contains ("xml") || uri.Contains ("rss") || uri.Contains ("feed") || uri.StartsWith ("itpc") || uri.StartsWith ("pcast")) {
+                // Handle normal XML/RSS URLs
                 if (uri.StartsWith ("feed://") || uri.StartsWith ("itpc://")) {
                     uri = String.Format ("http://{0}";, uri.Substring (7));
                 } else if (uri.StartsWith ("pcast://")) {
                     uri = String.Format ("http://{0}";, uri.Substring (8));
                 }
 
-                // TODO replace autodownload w/ actual default preference
-                FeedsManager.Instance.FeedManager.CreateFeed (uri, FeedAutoDownload.None);
-                source.NotifyUser ();
+                AddFeed (uri, null);
             } else if (uri.StartsWith ("itms://")) {
+                // Handle iTunes podcast URLs
                 System.Threading.ThreadPool.QueueUserWorkItem (delegate {
                     try {
-                        string feed_url = new ItmsPodcast (uri).FeedUrl;
-                        if (feed_url != null) {
+                        var feed = new ItmsPodcast (uri);
+                        if (feed.FeedUrl != null) {
                             ThreadAssist.ProxyToMain (delegate {
-                                FeedsManager.Instance.FeedManager.CreateFeed (feed_url, FeedAutoDownload.None);
-                                source.NotifyUser ();
+                                AddFeed (feed.FeedUrl, feed.Title);
                             });
                         }
                     } catch (Exception e) {
@@ -384,6 +387,14 @@ namespace Banshee.Podcasting
             }
         }
 
+        private void AddFeed (string uri, string title)
+        {
+            // TODO replace autodownload w/ actual default preference
+            FeedsManager.Instance.FeedManager.CreateFeed (uri, title, FeedAutoDownload.None);
+            source.NotifyUser ();
+            source.UpdateFeedMessages ();
+        }
+
         private void RefreshArtworkFor (Feed feed)
         {
             if (!String.IsNullOrEmpty (feed.ImageUrl) && !CoverArtSpec.CoverExists (PodcastService.ArtworkIdFor (feed))) {
@@ -441,6 +452,7 @@ namespace Banshee.Podcasting
         {
             source.Reload ();
             source.NotifyTracksChanged ();
+            source.UpdateFeedMessages ();
         }
 
         /*private void OnFeedAddedHandler (object sender, FeedEventArgs args)
diff --git a/src/Libraries/Migo/Migo.Syndication/Feed.cs b/src/Libraries/Migo/Migo.Syndication/Feed.cs
index 9a6924e..0a0f38f 100644
--- a/src/Libraries/Migo/Migo.Syndication/Feed.cs
+++ b/src/Libraries/Migo/Migo.Syndication/Feed.cs
@@ -144,9 +144,11 @@ namespace Migo.Syndication
             protected set { dbid = value; }
         }
 
+        public static string UnknownPodcastTitle = Catalog.GetString ("Unknown Podcast");
+
         [DatabaseColumn]
         public string Title {
-            get { return title ?? Catalog.GetString ("Unknown Podcast"); }
+            get { return title ?? UnknownPodcastTitle; }
             set { title = value; }
         }
 
diff --git a/src/Libraries/Migo/Migo.Syndication/FeedManager.cs b/src/Libraries/Migo/Migo.Syndication/FeedManager.cs
index 047042a..5724331 100644
--- a/src/Libraries/Migo/Migo.Syndication/FeedManager.cs
+++ b/src/Libraries/Migo/Migo.Syndication/FeedManager.cs
@@ -79,16 +79,22 @@ namespace Migo.Syndication
 
         public Feed CreateFeed (string url, FeedAutoDownload autoDownload)
         {
-            return CreateFeed (url, autoDownload, true);
+            return CreateFeed (url, null, autoDownload, true);
         }
 
-        public Feed CreateFeed (string url, FeedAutoDownload autoDownload, bool is_subscribed)
+        public Feed CreateFeed (string url, string title, FeedAutoDownload autoDownload)
+        {
+            return CreateFeed (url, title, autoDownload, true);
+        }
+
+        public Feed CreateFeed (string url, string title, FeedAutoDownload autoDownload, bool is_subscribed)
         {
             Feed feed = null;
             url = url.Trim ().TrimEnd ('/');
 
             if (!Feed.Exists (url)) {
                 feed = new Feed (url, autoDownload);
+                feed.Title = title;
                 feed.IsSubscribed = is_subscribed;
                 feed.Save ();
                 feed.Update ();
diff --git a/src/Libraries/Migo/Migo.Syndication/FeedUpdateTask.cs b/src/Libraries/Migo/Migo.Syndication/FeedUpdateTask.cs
index 4097c2c..8da31de 100644
--- a/src/Libraries/Migo/Migo.Syndication/FeedUpdateTask.cs
+++ b/src/Libraries/Migo/Migo.Syndication/FeedUpdateTask.cs
@@ -121,7 +121,7 @@ namespace Migo.Syndication
             try {
                 wc = new AsyncWebClient ();
                 wc.Timeout = (30 * 1000); // 30 Seconds
-                if (feed.LastDownloadTime != DateTime.MinValue) {
+                if (feed.LastDownloadError == FeedDownloadError.None && feed.LastDownloadTime != DateTime.MinValue) {
                     wc.IfModifiedSince = feed.LastDownloadTime.ToUniversalTime ();
                 }
                 wc.DownloadStringCompleted += OnDownloadDataReceived;
@@ -187,9 +187,7 @@ namespace Migo.Syndication
                 }
 
                 feed.LastDownloadError = error;
-                if (error == FeedDownloadError.None) {
-                    feed.LastDownloadTime = DateTime.Now;
-                }
+                feed.LastDownloadTime = DateTime.Now;
 
                 feed.Save (notify_on_save);
 



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