[rhythmbox] podcast: rework signals for feed update results
- From: Jonathan Matthew <jmatthew src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [rhythmbox] podcast: rework signals for feed update results
- Date: Sun, 6 Mar 2022 12:00:28 +0000 (UTC)
commit d2b486f509dc05f114fc0d4672d4f3b8151e627c
Author: Jonathan Matthew <jonathan d14n org>
Date: Sat Feb 19 16:15:50 2022 +1000
podcast: rework signals for feed update results
Now we have one signal that includes the feed url, the full range
of outcomes (hopefully) and optionally an error message.
Since this provides a convenient place to handle changes to feeds,
use this to redraw feed view rows when feeds are being updated.
podcast/rb-podcast-main-source.c | 111 +++++++++++++++++---------------
podcast/rb-podcast-manager.c | 134 ++++++++++++++++++++++++---------------
podcast/rb-podcast-manager.h | 14 ++++
podcast/rb-podcast-source.c | 20 ++++++
4 files changed, 176 insertions(+), 103 deletions(-)
---
diff --git a/podcast/rb-podcast-main-source.c b/podcast/rb-podcast-main-source.c
index 316bbf777..6133e9b51 100644
--- a/podcast/rb-podcast-main-source.c
+++ b/podcast/rb-podcast-main-source.c
@@ -39,6 +39,7 @@
#include "rb-file-helpers.h"
#include "rb-util.h"
#include "rb-application.h"
+#include "rb-debug.h"
struct _RBPodcastMainSourcePrivate
{
@@ -196,24 +197,6 @@ finish_download_cb (RBPodcastManager *pd,
g_free (secondary);
}
-static void
-feed_updates_available_cb (RBPodcastManager *pd,
- RhythmDBEntry *entry,
- RBPodcastMainSource *source)
-{
- RBShell *shell;
- char *podcast_name;
-
- podcast_name = g_markup_escape_text (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE), -1);
-
- g_object_get (source, "shell", &shell, NULL);
- rb_shell_notify_custom (shell, 4000, _("New updates available from"), podcast_name, NULL, FALSE);
- g_object_unref (shell);
-
- g_free (podcast_name);
-
-}
-
static void
error_dialog_response_cb (GtkDialog *dialog, int response, RBPodcastMainSource *source)
{
@@ -230,39 +213,68 @@ error_dialog_response_cb (GtkDialog *dialog, int response, RBPodcastMainSource *
}
static void
-feed_error_cb (RBPodcastManager *pd,
- const char *url,
- const char *error,
- gboolean existing,
- RBPodcastMainSource *source)
+feed_update_status_cb (RBPodcastManager *mgr, const char *url, RBPodcastFeedUpdateStatus status, const char
*error, gpointer data)
{
+ RBPodcastSource *source;
+ RhythmDBEntry *entry;
+ RBShell *shell;
+ char *podcast_name;
+ char *nice_error;
GtkWidget *dialog;
+ RhythmDB *db;
- /* if the podcast feed doesn't already exist in the db,
- * ask if the user wants to add it anyway; if it already
- * exists, there's nothing to do besides reporting the error.
- */
- dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (source))),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR,
- existing ? GTK_BUTTONS_OK : GTK_BUTTONS_YES_NO,
- _("Error in podcast"));
-
- if (existing) {
- gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
- "%s", error);
- } else {
- gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
- _("%s. Would you like to add the podcast feed
anyway?"), error);
- }
+ source = data;
+ g_object_get (source, "shell", &shell, NULL);
+ g_object_get (shell, "db", &db, NULL);
+
+ entry = rhythmdb_entry_lookup_by_location (db, url);
+
+ switch (status) {
+ case RB_PODCAST_FEED_UPDATE_ERROR:
+ /* if the podcast feed doesn't already exist in the db,
+ * ask if the user wants to add it anyway; if it already
+ * exists, there's nothing to do besides reporting the error.
+ */
+ dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (source))),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ (entry != NULL) ? GTK_BUTTONS_OK : GTK_BUTTONS_YES_NO,
+ _("Error in podcast"));
+
+ nice_error = g_strdup_printf (_("There was a problem adding this podcast: %s. Please verify
the URL: %s"), error, url);
+ if (entry != NULL) {
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ "%s", nice_error);
+ } else {
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ _("%s. Would you like to add the podcast
feed anyway?"), nice_error);
+ }
+ g_free (nice_error);
+
+ gtk_window_set_title (GTK_WINDOW (dialog), "");
+ gtk_container_set_border_width (GTK_CONTAINER (dialog), 6);
+
+ g_object_set_data_full (G_OBJECT (dialog), "feed-url", g_strdup (url), g_free);
+ g_signal_connect (dialog, "response", G_CALLBACK (error_dialog_response_cb), source);
+
+ gtk_widget_show_all (dialog);
+
+ break;
- gtk_window_set_title (GTK_WINDOW (dialog), "");
- gtk_container_set_border_width (GTK_CONTAINER (dialog), 6);
+ case RB_PODCAST_FEED_UPDATE_UPDATED:
+ podcast_name = g_markup_escape_text (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE),
-1);
- g_object_set_data_full (G_OBJECT (dialog), "feed-url", g_strdup (url), g_free);
- g_signal_connect (dialog, "response", G_CALLBACK (error_dialog_response_cb), source);
+ rb_shell_notify_custom (shell, 4000, _("New updates available from"), podcast_name, NULL,
FALSE);
- gtk_widget_show_all (dialog);
+ g_free (podcast_name);
+ break;
+
+ default:
+ break;
+ }
+
+ g_object_unref (shell);
+ g_object_unref (db);
}
static void
@@ -387,13 +399,8 @@ impl_constructed (GObject *object)
source, 0);
g_signal_connect_object (podcast_mgr,
- "feed_updates_available",
- G_CALLBACK (feed_updates_available_cb),
- source, 0);
-
- g_signal_connect_object (podcast_mgr,
- "feed-parse-error",
- G_CALLBACK (feed_error_cb),
+ "feed-update-status",
+ G_CALLBACK (feed_update_status_cb),
source, 0);
rb_display_page_set_icon_name (RB_DISPLAY_PAGE (source), "application-rss+xml-symbolic");
diff --git a/podcast/rb-podcast-manager.c b/podcast/rb-podcast-manager.c
index b390b1d6e..be3398704 100644
--- a/podcast/rb-podcast-manager.c
+++ b/podcast/rb-podcast-manager.c
@@ -68,8 +68,8 @@ enum
{
START_DOWNLOAD,
FINISH_DOWNLOAD,
- FEED_PARSE_ERROR,
- FEED_UPDATES_AVAILABLE,
+ FEED_UPDATE_STATUS,
+
LAST_SIGNAL
};
@@ -209,29 +209,18 @@ rb_podcast_manager_class_init (RBPodcastManagerClass *klass)
RHYTHMDB_TYPE_ENTRY,
G_TYPE_ERROR);
- rb_podcast_manager_signals[FEED_UPDATES_AVAILABLE] =
- g_signal_new ("feed_updates_available",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL,
- NULL,
- G_TYPE_NONE,
- 1,
- RHYTHMDB_TYPE_ENTRY);
-
- rb_podcast_manager_signals[FEED_PARSE_ERROR] =
- g_signal_new ("feed-parse-error",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL,
- NULL,
- G_TYPE_NONE,
- 3,
- G_TYPE_STRING,
- G_TYPE_STRING,
- G_TYPE_BOOLEAN);
+ rb_podcast_manager_signals[FEED_UPDATE_STATUS] =
+ g_signal_new ("feed-update-status",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE,
+ 3,
+ G_TYPE_STRING,
+ RB_TYPE_PODCAST_FEED_UPDATE_STATUS,
+ G_TYPE_STRING);
g_type_class_add_private (klass, sizeof (RBPodcastManagerPrivate));
}
@@ -706,14 +695,20 @@ rb_podcast_manager_feed_updating (RBPodcastManager *pm, const char *url)
return FALSE;
}
+static void
+emit_feed_update_status (RBPodcastManager *mgr, RBPodcastChannel *channel, RBPodcastFeedUpdateStatus status,
const char *error)
+{
+ g_signal_emit (mgr, rb_podcast_manager_signals[FEED_UPDATE_STATUS], 0, channel->url, status, error);
+}
+
static void
feed_parse_cb (RBPodcastChannel *channel, GError *error, gpointer user_data)
{
RBPodcastUpdate *update = user_data;
RBPodcastManager *pd = update->pd;
+ RBPodcastFeedUpdateStatus status;
RhythmDBEntry *entry;
GValue v = {0,};
- gboolean existing = FALSE;
if (error == NULL) {
if (channel->is_opml) {
@@ -726,12 +721,15 @@ feed_parse_cb (RBPodcastChannel *channel, GError *error, gpointer user_data)
/* assume the feeds don't already exist */
rb_podcast_manager_subscribe_feed (pd, item->url, FALSE);
}
+
+ emit_feed_update_status (pd, channel, RB_PODCAST_FEED_UPDATE_SUBSCRIBED, NULL);
} else {
rb_podcast_manager_add_parsed_feed (pd, channel);
}
} else if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
rb_debug ("podcast update cancelled");
- g_error_free (error);
+
+ emit_feed_update_status (pd, channel, RB_PODCAST_FEED_UPDATE_CANCELLED, NULL);
} else {
/* set the error in the feed entry, if one exists */
entry = rhythmdb_entry_lookup_by_location (pd->priv->db, channel->url);
@@ -747,20 +745,14 @@ feed_parse_cb (RBPodcastChannel *channel, GError *error, gpointer user_data)
g_value_unset (&v);
rhythmdb_commit (pd->priv->db);
- existing = TRUE;
}
- /* if this was a result of a direct user action, emit the error signal too */
- if (update->automatic) {
- gchar *error_msg;
- error_msg = g_strdup_printf (_("There was a problem adding this podcast: %s. Please
verify the URL: %s"),
- error->message, channel->url);
- g_signal_emit (pd,
- rb_podcast_manager_signals[FEED_PARSE_ERROR],
- 0, channel->url, error_msg, existing);
- g_free (error_msg);
- }
- g_error_free (error);
+ if (update->automatic)
+ status = RB_PODCAST_FEED_UPDATE_ERROR_BG;
+ else
+ status = RB_PODCAST_FEED_UPDATE_ERROR;
+
+ emit_feed_update_status (pd, channel, status, error->message);
}
podcast_update_free (update);
@@ -778,6 +770,7 @@ confirm_bad_mime_type_response_cb (GtkDialog *dialog, int response, RBPodcastUpd
if (response == GTK_RESPONSE_YES) {
start_feed_parse (update->pd, update);
} else {
+ emit_feed_update_status (update->pd, update->channel, RB_PODCAST_FEED_UPDATE_CANCELLED, NULL);
podcast_update_free (update);
}
@@ -797,6 +790,7 @@ mime_type_check_cb (GObject *source_object, GAsyncResult *res, gpointer user_dat
if (file_info == NULL) {
g_object_unref (source_object);
feed_parse_cb (update->channel, error, update);
+ g_clear_error (&error);
return;
}
@@ -858,6 +852,8 @@ rb_podcast_manager_subscribe_feed (RBPodcastManager *pd, const char *url, gboole
if (g_list_length (pd->priv->updating) == 1)
g_object_notify (G_OBJECT (pd), "updating");
+ emit_feed_update_status (pd, update->channel, RB_PODCAST_FEED_UPDATE_STARTED, NULL);
+
entry = rhythmdb_entry_lookup_by_location (pd->priv->db, feed_url);
if (entry) {
GValue v = {0,};
@@ -868,6 +864,8 @@ rb_podcast_manager_subscribe_feed (RBPodcastManager *pd, const char *url, gboole
"If this is a podcast feed, please remove the radio station."), url);
g_object_unref (feed);
g_free (feed_url);
+
+ emit_feed_update_status (pd, update->channel, RB_PODCAST_FEED_UPDATE_CONFLICT, NULL);
podcast_update_free (update);
return FALSE;
}
@@ -1379,7 +1377,7 @@ rb_podcast_manager_add_parsed_feed (RBPodcastManager *pd, RBPodcastChannel *data
gulong position;
const char *title;
GList *download_entries = NULL;
- gboolean new_feed, updated;
+ gboolean new_feed;
RhythmDB *db = pd->priv->db;
RhythmDBQueryResultList *results = NULL;
GList *existing_entries = NULL;
@@ -1388,18 +1386,19 @@ rb_podcast_manager_add_parsed_feed (RBPodcastManager *pd, RBPodcastChannel *data
DOWNLOAD_NEWEST,
DOWNLOAD_NEW
} download_mode;
-
RhythmDBEntry *entry;
-
GList *l;
+ RBPodcastFeedUpdateStatus status = RB_PODCAST_FEED_UPDATE_UNCHANGED;
new_feed = TRUE;
/* processing podcast head */
entry = rhythmdb_entry_lookup_by_location (db, (gchar *)data->url);
if (entry) {
- if (rhythmdb_entry_get_entry_type (entry) != RHYTHMDB_ENTRY_TYPE_PODCAST_FEED)
+ if (rhythmdb_entry_get_entry_type (entry) != RHYTHMDB_ENTRY_TYPE_PODCAST_FEED) {
+ emit_feed_update_status (pd, data, RB_PODCAST_FEED_UPDATE_CONFLICT, NULL);
return;
+ }
rb_debug ("Podcast feed entry for %s found", data->url);
g_value_init (&val, G_TYPE_ULONG);
@@ -1428,13 +1427,17 @@ rb_podcast_manager_add_parsed_feed (RBPodcastManager *pd, RBPodcastChannel *data
entry = rhythmdb_entry_new (db,
RHYTHMDB_ENTRY_TYPE_PODCAST_FEED,
(gchar *) data->url);
- if (entry == NULL)
+ if (entry == NULL) {
+ emit_feed_update_status (pd, data, RB_PODCAST_FEED_UPDATE_CONFLICT, NULL);
return;
+ }
g_value_init (&val, G_TYPE_ULONG);
g_value_set_ulong (&val, RHYTHMDB_PODCAST_FEED_STATUS_NORMAL);
rhythmdb_entry_set (db, entry, RHYTHMDB_PROP_STATUS, &val);
g_value_unset (&val);
+
+ status = RB_PODCAST_FEED_UPDATE_SUBSCRIBED;
}
/* if the feed does not contain a title, use the URL instead */
@@ -1517,12 +1520,13 @@ rb_podcast_manager_add_parsed_feed (RBPodcastManager *pd, RBPodcastChannel *data
/* insert episodes */
new_last_post = last_post;
- updated = FALSE;
position = 1;
for (l = data->posts; l != NULL; l = g_list_next (l)) {
RBPodcastItem *item = (RBPodcastItem *) l->data;
RhythmDBEntry *post_entry;
+ gboolean new_entry;
+ new_entry = TRUE;
if (existing_entries != NULL) {
GList *l;
const char *guid;
@@ -1546,6 +1550,7 @@ rb_podcast_manager_add_parsed_feed (RBPodcastManager *pd, RBPodcastChannel *data
/* mark this entry as still being available */
existing_entries = g_list_remove_link (existing_entries, l);
g_list_free (l);
+ new_entry = FALSE;
} else {
rb_debug ("episode url %s (guid %s) not matched", item->url, item->guid);
post_entry = NULL;
@@ -1571,8 +1576,11 @@ rb_podcast_manager_add_parsed_feed (RBPodcastManager *pd, RBPodcastChannel *data
position++,
item->filesize);
- if (post_entry)
- updated = TRUE;
+ if (new_entry && (post_entry != NULL)) {
+ if (status == RB_PODCAST_FEED_UPDATE_UNCHANGED) {
+ status = RB_PODCAST_FEED_UPDATE_UPDATED;
+ }
+ }
if (post_entry && item->pub_date >= new_last_post) {
switch (download_mode) {
@@ -1606,10 +1614,6 @@ rb_podcast_manager_add_parsed_feed (RBPodcastManager *pd, RBPodcastChannel *data
}
g_list_free (download_entries);
- if (updated)
- g_signal_emit (pd, rb_podcast_manager_signals[FEED_UPDATES_AVAILABLE],
- 0, entry);
-
if (data->pub_date > new_last_post)
new_last_post = data->pub_date;
@@ -1641,6 +1645,8 @@ rb_podcast_manager_add_parsed_feed (RBPodcastManager *pd, RBPodcastChannel *data
g_clear_object (&results);
rhythmdb_commit (db);
+
+ emit_feed_update_status (pd, data, status, NULL);
}
void
@@ -2309,3 +2315,29 @@ cancel_download (RBPodcastDownload *data)
return FALSE;
}
}
+
+#define ENUM_ENTRY(name, desc) { name, "" #name "", desc }
+
+GType
+rb_podcast_feed_update_status_get_type (void)
+{
+ static GType etype = 0;
+
+ if (etype == 0) {
+ static const GEnumValue values[] = {
+ ENUM_ENTRY (RB_PODCAST_FEED_UPDATE_STARTED, "started"),
+ ENUM_ENTRY (RB_PODCAST_FEED_UPDATE_ERROR, "error"),
+ ENUM_ENTRY (RB_PODCAST_FEED_UPDATE_ERROR_BG, "error-background"),
+ ENUM_ENTRY (RB_PODCAST_FEED_UPDATE_CONFLICT, "conflict"),
+ ENUM_ENTRY (RB_PODCAST_FEED_UPDATE_CANCELLED, "cancelled"),
+ ENUM_ENTRY (RB_PODCAST_FEED_UPDATE_SUBSCRIBED, "subscribed"),
+ ENUM_ENTRY (RB_PODCAST_FEED_UPDATE_UNCHANGED, "unchanged"),
+ ENUM_ENTRY (RB_PODCAST_FEED_UPDATE_UPDATED, "updated"),
+ { 0, 0, 0 }
+ };
+
+ etype = g_enum_register_static ("RBPodcastFeedUpdateStatus", values);
+ }
+
+ return etype;
+}
diff --git a/podcast/rb-podcast-manager.h b/podcast/rb-podcast-manager.h
index fbf07bf80..83758e7b7 100644
--- a/podcast/rb-podcast-manager.h
+++ b/podcast/rb-podcast-manager.h
@@ -36,6 +36,20 @@
G_BEGIN_DECLS
+typedef enum {
+ RB_PODCAST_FEED_UPDATE_STARTED = 0,
+ RB_PODCAST_FEED_UPDATE_ERROR,
+ RB_PODCAST_FEED_UPDATE_ERROR_BG,
+ RB_PODCAST_FEED_UPDATE_CONFLICT,
+ RB_PODCAST_FEED_UPDATE_CANCELLED,
+ RB_PODCAST_FEED_UPDATE_SUBSCRIBED,
+ RB_PODCAST_FEED_UPDATE_UNCHANGED,
+ RB_PODCAST_FEED_UPDATE_UPDATED
+} RBPodcastFeedUpdateStatus;
+
+GType rb_podcast_feed_update_status_get_type (void);
+#define RB_TYPE_PODCAST_FEED_UPDATE_STATUS (rb_podcast_feed_update_status_get_type())
+
#define RB_TYPE_PODCAST_MANAGER (rb_podcast_manager_get_type ())
#define RB_PODCAST_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), RB_TYPE_PODCAST_MANAGER,
RBPodcastManager))
#define RB_PODCAST_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), RB_TYPE_PODCAST_MANAGER,
RBPodcastManagerClass))
diff --git a/podcast/rb-podcast-source.c b/podcast/rb-podcast-source.c
index dd391475f..8fc97b728 100644
--- a/podcast/rb-podcast-source.c
+++ b/podcast/rb-podcast-source.c
@@ -1230,6 +1230,25 @@ impl_get_status (RBDisplayPage *page, char **text, gboolean *busy)
g_object_get (source->priv->podcast_mgr, "updating", busy, NULL);
}
+static void
+feed_update_status_cb (RBPodcastManager *mgr,
+ const char *url,
+ RBPodcastFeedUpdateStatus status,
+ const char *error,
+ gpointer data)
+{
+ RBPodcastSource *source = RB_PODCAST_SOURCE (data);
+ GtkTreeIter iter;
+
+ if (rhythmdb_property_model_iter_from_string (source->priv->feed_model, url, &iter)) {
+ GtkTreePath *path;
+
+ path = gtk_tree_model_get_path (GTK_TREE_MODEL (source->priv->feed_model), &iter);
+ gtk_tree_model_row_changed (GTK_TREE_MODEL (source->priv->feed_model), path, &iter);
+ gtk_tree_path_free (path);
+ }
+}
+
static void
podcast_manager_updating_cb (GObject *obj, GParamSpec *pspec, gpointer data)
{
@@ -1588,6 +1607,7 @@ impl_constructed (GObject *object)
g_object_unref (accel_group);
g_object_unref (shell);
+ g_signal_connect_object (source->priv->podcast_mgr, "feed-update-status", G_CALLBACK
(feed_update_status_cb), source, 0);
g_signal_connect (source->priv->podcast_mgr, "notify::updating", G_CALLBACK
(podcast_manager_updating_cb), source);
rb_podcast_source_do_query (source, TRUE);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]