276 lines
9.0 KiB
Diff
276 lines
9.0 KiB
Diff
|
From a3a69d76e25358fc05c99e57041fa1485486345f Mon Sep 17 00:00:00 2001
|
||
|
From: Robert Ancell <robert.ancell@canonical.com>
|
||
|
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
|
||
|
|