From a3a69d76e25358fc05c99e57041fa1485486345f Mon Sep 17 00:00:00 2001 From: Robert Ancell Date: Thu, 15 Oct 2009 16:28:32 +1100 Subject: [PATCH] Support using g_file_input_stream_query_info() to get file information for podcasts. This means only one connection to the server is required instead of two when using g_file_query_info() --- podcast/rb-podcast-manager.c | 149 ++++++++++++++++++++++++++---------------- 1 files changed, 92 insertions(+), 57 deletions(-) diff --git a/podcast/rb-podcast-manager.c b/podcast/rb-podcast-manager.c index eb6c821..bc1695b 100644 --- a/podcast/rb-podcast-manager.c +++ b/podcast/rb-podcast-manager.c @@ -153,9 +153,14 @@ static void rb_podcast_manager_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); +static void read_file_cb (GFile *source, + GAsyncResult *result, + RBPodcastManagerInfo *data); static void download_file_info_cb (GFile *source, GAsyncResult *result, RBPodcastManagerInfo *data); +static void download_podcast (GFileInfo *src_info, + RBPodcastManagerInfo *data); static void rb_podcast_manager_abort_download (RBPodcastManagerInfo *data); static gboolean rb_podcast_manager_sync_head_cb (gpointer data); static gboolean rb_podcast_manager_head_query_cb (GtkTreeModel *query_model, @@ -618,7 +623,7 @@ rb_podcast_manager_head_query_cb (GtkTreeModel *query_model, } static void -download_error (RBPodcastManagerInfo *data, GError *error) +download_error (RBPodcastManagerInfo *data, GError *error, gboolean in_thread) { GValue val = {0,}; rb_debug ("error downloading %s: %s", @@ -636,7 +641,12 @@ download_error (RBPodcastManagerInfo *data, GError *error) g_value_unset (&val); rhythmdb_commit (data->pd->priv->db); - g_idle_add ((GSourceFunc)end_job, data); + + if (in_thread) { + g_idle_add ((GSourceFunc)end_job, data); + } else { + rb_podcast_manager_abort_download (data); + } } static gboolean @@ -645,7 +655,6 @@ rb_podcast_manager_next_file (RBPodcastManager * pd) const char *location; RBPodcastManagerInfo *data; char *query_string; - const char *attrs; GList *d; g_assert (rb_is_main_thread ()); @@ -689,69 +698,103 @@ rb_podcast_manager_next_file (RBPodcastManager * pd) data->source = g_file_new_for_uri (location); - attrs = G_FILE_ATTRIBUTE_STANDARD_SIZE "," - G_FILE_ATTRIBUTE_STANDARD_COPY_NAME "," - G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME; - g_file_query_info_async (data->source, - attrs, - G_FILE_QUERY_INFO_NONE, - 0, - data->cancel, - (GAsyncReadyCallback) download_file_info_cb, - data); + g_file_read_async (data->source, + 0, + data->cancel, + (GAsyncReadyCallback) read_file_cb, + data); GDK_THREADS_LEAVE (); return FALSE; } static void -download_file_info_cb (GFile *source, - GAsyncResult *result, - RBPodcastManagerInfo *data) +read_file_cb (GFile *source, + GAsyncResult *result, + RBPodcastManagerInfo *data) { GError *error = NULL; GFileInfo *src_info; - char *local_file_name = NULL; - char *feed_folder; - char *esc_local_file_name; - char *local_file_uri; - char *sane_local_file_uri; - char *conf_dir_uri; g_assert (rb_is_main_thread ()); - rb_debug ("got file info results for %s", + rb_debug ("started read for %s", get_remote_location (data->entry)); - src_info = g_file_query_info_finish (source, result, &error); - - /* ignore G_IO_ERROR_FAILED here, as it probably just means that the server is lame. - * actual problems (not found, permission denied, etc.) have specific errors codes, - * so they'll still be reported. + data->in_stream = g_file_read_finish (data->source, + result, + &error); + if (error != NULL) { + download_error (data, error, FALSE); + g_error_free (error); + return; + } + + src_info = g_file_input_stream_query_info (data->in_stream, + G_FILE_ATTRIBUTE_STANDARD_SIZE "," + G_FILE_ATTRIBUTE_STANDARD_COPY_NAME "," + G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME, + NULL, + &error); + + /* If no stream information then probably using an old version of gvfs, fall back + * to getting the stream information from the GFile. + * This branch can be removed when this version of gvfs is released, see: + * https://bugzilla.gnome.org/show_bug.cgi?id=598505 */ - if (error != NULL && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_FAILED) == FALSE) { - GValue val = {0,}; + if (error != NULL) { + rb_debug ("file info query from input failed, trying query on file: %s", error->message); + g_error_free (error); - rb_debug ("file info query failed: %s", error->message); + g_file_query_info_async (data->source, + G_FILE_ATTRIBUTE_STANDARD_SIZE "," + G_FILE_ATTRIBUTE_STANDARD_COPY_NAME "," + G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME, + G_FILE_QUERY_INFO_NONE, + 0, + data->cancel, + (GAsyncReadyCallback) download_file_info_cb, + data); + return; + } - g_value_init (&val, G_TYPE_ULONG); - g_value_set_ulong (&val, RHYTHMDB_PODCAST_STATUS_ERROR); - rhythmdb_entry_set (data->pd->priv->db, data->entry, RHYTHMDB_PROP_STATUS, &val); - g_value_unset (&val); + rb_debug ("got file info results for %s", + get_remote_location (data->entry)); - g_value_init (&val, G_TYPE_STRING); - g_value_set_string (&val, error->message); - rhythmdb_entry_set (data->pd->priv->db, data->entry, RHYTHMDB_PROP_PLAYBACK_ERROR, &val); - g_value_unset (&val); + download_podcast (src_info, data); +} - rhythmdb_commit (data->pd->priv->db); +static void +download_file_info_cb (GFile *source, + GAsyncResult *result, + RBPodcastManagerInfo *data) +{ + GError *error = NULL; + GFileInfo *src_info; + + src_info = g_file_query_info_finish (source, result, &error); + if (error != NULL) { + download_error (data, error, FALSE); g_error_free (error); - rb_podcast_manager_abort_download (data); - return; } else { - g_clear_error (&error); + rb_debug ("got file info results for %s", + get_remote_location (data->entry)); + + download_podcast (src_info, data); } +} + +static void +download_podcast (GFileInfo *src_info, RBPodcastManagerInfo *data) +{ + GError *error = NULL; + char *local_file_name = NULL; + char *feed_folder; + char *esc_local_file_name; + char *local_file_uri; + char *sane_local_file_uri; + char *conf_dir_uri; if (src_info != NULL) { data->download_size = g_file_info_get_attribute_uint64 (src_info, G_FILE_ATTRIBUTE_STANDARD_SIZE); @@ -769,7 +812,7 @@ download_file_info_cb (GFile *source, if (local_file_name == NULL) { /* fall back to the basename from the original URI */ - local_file_name = g_file_get_basename (source); + local_file_name = g_file_get_basename (data->source); rb_debug ("didn't get a filename from the file info request; using basename %s", local_file_name); } @@ -819,7 +862,6 @@ download_file_info_cb (GFile *source, return; } - data->destination = g_file_new_for_uri (sane_local_file_uri); if (g_file_query_exists (data->destination, NULL)) { GFileInfo *dest_info; @@ -892,7 +934,7 @@ download_file_info_cb (GFile *source, TRUE, &error); if (error != NULL) { - download_error (data, error); + download_error (data, error, TRUE); g_error_free (error); } } @@ -1407,14 +1449,6 @@ podcast_download_thread (RBPodcastManagerInfo *data) gssize n_read; gssize n_written; guint64 downloaded; - - /* open remote file */ - data->in_stream = g_file_read (data->source, data->cancel, &error); - if (error != NULL) { - download_error (data, error); - g_error_free (error); - return NULL; - } /* if we have an offset to download from, try the seek * before anything else. if we can't seek, we'll have to @@ -1443,7 +1477,7 @@ podcast_download_thread (RBPodcastManagerInfo *data) } } if (error != NULL) { - download_error (data, error); + download_error (data, error, TRUE); g_error_free (error); return NULL; } @@ -1491,7 +1525,7 @@ podcast_download_thread (RBPodcastManagerInfo *data) data->cancel, &error); if (error != NULL) { - download_error (data, error); + download_error (data, error, TRUE); g_error_free (error); return NULL; } @@ -1535,7 +1569,8 @@ podcast_download_thread (RBPodcastManagerInfo *data) g_object_unref (data->out_stream); if (error != NULL) { - download_error (data, error); + download_error (data, error, TRUE); + g_error_free (error); } else { download_progress (data, downloaded, data->download_size, TRUE); } -- 1.6.3.3