[totem/gnome-3-8] chapters: Refactor async chapters loading
- From: Bastien Nocera <hadess src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [totem/gnome-3-8] chapters: Refactor async chapters loading
- Date: Wed, 6 Mar 2013 16:55:24 +0000 (UTC)
commit 1bac82142ced8532c549753be7cb982816fdcc25
Author: Bastien Nocera <hadess hadess net>
Date: Wed Mar 6 13:31:48 2013 +0100
chapters: Refactor async chapters loading
Using GIO-style async functions which can be properly cancelled.
https://bugzilla.gnome.org/show_bug.cgi?id=692731
src/plugins/chapters/totem-chapters.c | 86 ++++++++++--------------
src/plugins/chapters/totem-cmml-parser.c | 105 ++++++++++++++++++------------
src/plugins/chapters/totem-cmml-parser.h | 9 ++-
3 files changed, 106 insertions(+), 94 deletions(-)
---
diff --git a/src/plugins/chapters/totem-chapters.c b/src/plugins/chapters/totem-chapters.c
index dfffc89..dec42c7 100644
--- a/src/plugins/chapters/totem-chapters.c
+++ b/src/plugins/chapters/totem-chapters.c
@@ -98,7 +98,7 @@ enum {
};
static void totem_file_opened_async_cb (TotemObject *totem, const gchar *uri, TotemChaptersPlugin *plugin);
-static void totem_file_opened_result_cb (gpointer data, gpointer user_data);
+static void totem_file_opened_result_cb (GObject *source_object, GAsyncResult *res, gpointer user_data);
static void totem_file_closed_cb (TotemObject *totem, TotemChaptersPlugin *plugin);
static void add_chapter_to_the_list (gpointer data, gpointer user_data);
static void add_chapter_to_the_list_new (TotemChaptersPlugin *plugin, const gchar *title, gint64 time);
@@ -303,48 +303,47 @@ check_available_time (TotemChaptersPlugin *plugin,
}
static void
-totem_file_opened_result_cb (gpointer data,
- gpointer user_data)
+totem_file_opened_result_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
{
- TotemCmmlAsyncData *adata;
- TotemChaptersPlugin *plugin;
-
- g_return_if_fail (data != NULL);
-
- adata = (TotemCmmlAsyncData *) data;
- plugin = TOTEM_CHAPTERS_PLUGIN (adata->user_data);
+ TotemChaptersPlugin *plugin = TOTEM_CHAPTERS_PLUGIN (user_data);
+ GError *error = NULL;
+ GList *list;
+ gboolean from_dialog;
+ gboolean is_exists;
+
+ is_exists = TRUE;
+ list = totem_cmml_read_file_finish (G_FILE (source_object), res, &error);
+
+ if (list == NULL) {
+ /* Ignore errors if file is not present */
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND) &&
+ !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED)) {
+ totem_action_error (plugin->priv->totem, _("Error while reading file with chapters"),
+ error->message);
+ g_error_free (error);
- if (G_UNLIKELY (!adata->successful)) {
- if (G_UNLIKELY (g_cancellable_is_cancelled (adata->cancellable))) {
- /* if operation was cancelled due to plugin deactivation only clean up */
- g_object_unref (adata->cancellable);
- g_free (adata->file);
- g_free (adata->error);
- g_list_foreach (adata->list, (GFunc) totem_cmml_clip_free, NULL);
- g_list_free (adata->list);
- g_free (adata);
+ set_no_data_visible (TRUE, TRUE, plugin);
return;
- } else
- totem_action_error (plugin->priv->totem, _("Error while reading file with chapters"),
- adata->error);
+ }
+ g_error_free (error);
+ is_exists = FALSE;
}
- if (adata->is_exists && adata->from_dialog) {
+ from_dialog = GPOINTER_TO_INT(g_object_get_data (source_object, "from-dialog"));
+
+ if (from_dialog) {
g_free (plugin->priv->cmml_mrl);
- plugin->priv->cmml_mrl = g_strdup (adata->file);
+ plugin->priv->cmml_mrl = g_file_get_uri (G_FILE (source_object));
}
- g_list_foreach (adata->list, (GFunc) add_chapter_to_the_list, plugin);
- g_list_foreach (adata->list, (GFunc) totem_cmml_clip_free, NULL);
- g_list_free (adata->list);
+ g_list_foreach (list, (GFunc) add_chapter_to_the_list, plugin);
+ g_list_foreach (list, (GFunc) totem_cmml_clip_free, NULL);
+ g_list_free (list);
/* do not show tree if read operation failed */
- set_no_data_visible (!adata->successful || !adata->is_exists, TRUE, plugin);
-
- g_object_unref (adata->cancellable);
- g_free (adata->file);
- g_free (adata->error);
- g_free (adata);
+ set_no_data_visible (!is_exists, TRUE, plugin);
}
static void
@@ -607,7 +606,7 @@ load_chapters_from_file (const gchar *uri,
gboolean from_dialog,
TotemChaptersPlugin *plugin)
{
- TotemCmmlAsyncData *data;
+ GFile *file;
g_return_if_fail (TOTEM_IS_CHAPTERS_PLUGIN (plugin));
@@ -616,27 +615,14 @@ load_chapters_from_file (const gchar *uri,
g_object_unref (plugin->priv->cancellable[0]);
}
- data = g_new0 (TotemCmmlAsyncData, 1);
- /* do not forget to save this pointer in the result function */
- data->file = g_strdup (uri);
- data->final = totem_file_opened_result_cb;
- data->user_data = (gpointer) plugin;
- if (from_dialog)
- data->from_dialog = TRUE;
+ file = g_file_new_for_uri (uri);
+ g_object_set_data (G_OBJECT (file), "from-dialog", GINT_TO_POINTER (from_dialog));
/* cancellable object shouldn't be finalized during result func */
plugin->priv->cancellable[0] = g_cancellable_new ();
g_object_add_weak_pointer (G_OBJECT (plugin->priv->cancellable[0]),
(gpointer *) &(plugin->priv->cancellable[0]));
- data->cancellable = plugin->priv->cancellable[0];
-
- if (G_UNLIKELY (totem_cmml_read_file_async (data) < 0)) {
- g_warning ("chapters: wrong parameters for reading CMML file, may be a bug");
-
- set_no_data_visible (TRUE, TRUE, plugin);
- g_object_unref (plugin->priv->cancellable[0]);
- g_free (data);
- }
+ totem_cmml_read_file (file, plugin->priv->cancellable[0], totem_file_opened_result_cb, plugin);
}
static void
diff --git a/src/plugins/chapters/totem-cmml-parser.c b/src/plugins/chapters/totem-cmml-parser.c
index e0ca7b2..39dc19d 100644
--- a/src/plugins/chapters/totem-cmml-parser.c
+++ b/src/plugins/chapters/totem-cmml-parser.c
@@ -607,55 +607,45 @@ totem_cmml_clip_copy (TotemCmmlClip *clip)
}
static void
-totem_cmml_read_file_result (GObject *source_object,
- GAsyncResult *result,
- gpointer user_data)
+totem_cmml_read_file_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
{
GError *error = NULL;
xmlTextReaderPtr reader;
TotemCmmlContext *context;
- TotemCmmlAsyncData *data;
gint ret;
gchar *contents;
gsize length;
+ gboolean load_ret;
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data);
+ GList *list = NULL;
- data = (TotemCmmlAsyncData *) user_data;
- data->is_exists = TRUE;
-
- g_file_load_contents_finish (G_FILE (source_object), result, &contents, &length, NULL, &error);
+ load_ret = g_file_load_contents_finish (G_FILE (source_object), result, &contents, &length, NULL,
&error);
g_object_unref (source_object);
- if (G_UNLIKELY (error != NULL)) {
- if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND) ||
- g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED)) {
- /* it's ok if file doesn't exist */
- data->successful = TRUE;
- data->is_exists = FALSE;
- } else {
- data->successful = FALSE;
- data->error = g_strdup (error->message);
- g_warning ("chapters: failed to load CMML file %s: %s", data->file, error->message);
- }
+ if (!load_ret) {
+ g_simple_async_result_set_from_error (simple, error);
+ g_simple_async_result_complete_in_idle (simple);
+ g_object_unref (simple);
g_error_free (error);
- (data->final) (data, NULL);
return;
}
/* parse in-memory xml data */
reader = xmlReaderForMemory (contents, length, "", NULL, 0);
if (G_UNLIKELY (reader == NULL)) {
- g_warning ("chapters: failed to parse CMML file %s", data->file);
- g_free (contents);
- data->successful = FALSE;
- data->error = g_strdup (_("Failed to parse CMML file"));
- (data->final) (data, NULL);
+ g_simple_async_result_set_error (simple, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Failed to parse CMML file");
+ g_simple_async_result_complete_in_idle (simple);
+ g_object_unref (simple);
return;
}
context = totem_cmml_context_new ();
context->reader = reader;
- totem_cmml_context_set_callback (context, totem_cmml_read_clip_cb, &(data->list));
+ totem_cmml_context_set_callback (context, totem_cmml_read_clip_cb, &list);
ret = xmlTextReaderRead (reader);
while (ret == 1) {
@@ -669,32 +659,61 @@ totem_cmml_read_file_result (GObject *source_object,
totem_cmml_context_free (context);
/* sort clips by time growth */
- data->list = g_list_sort (data->list, (GCompareFunc) totem_cmml_compare_clips);
- data->successful = TRUE;
- (data->final) (data, NULL);
+ list = g_list_sort (list, (GCompareFunc) totem_cmml_compare_clips);
+
+ g_simple_async_result_set_op_res_gpointer (simple, list, NULL);
+ g_simple_async_result_complete_in_idle (simple);
+ g_object_unref (simple);
}
/**
- * totem_cmml_read_file_async:
- * @data: #TotemCmmlAsyncData structure with info needed
+ * totem_cmml_read_file:
+ * @file: a #GFile representing the file to read
+ * @cancellable: optional #GCancellable object, %NULL to ignore
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied.
+ * @user_data: the data to pass to callback function.
*
- * Reads CMML file and parse it for clips in async way.
+ * Reads and parses a CMML file asynchronously.
+ **/
+void
+totem_cmml_read_file (GFile *file,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple;
+
+ simple = g_simple_async_result_new (G_OBJECT (file),
+ callback,
+ user_data,
+ totem_cmml_read_file);
+
+ g_file_load_contents_async (file, cancellable, totem_cmml_read_file_cb, simple);
+}
+
+/**
+ * totem_ccml_read_file_finish:
+ * @file: a #GFile representing the file to read
+ * @res: a #GAsyncResult
+ * @error: a #GError, or %NULL
*
- * Returns: 0 if no errors occurred while starting async reading, -1 otherwise.
+ * Returns a list of parsed chapters or %NULL on error
**/
-gint
-totem_cmml_read_file_async (TotemCmmlAsyncData *data)
+GList *
+totem_cmml_read_file_finish (GFile *file,
+ GAsyncResult *res,
+ GError **error)
{
- GFile *gio_file;
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
- g_return_val_if_fail (data != NULL, -1);
- g_return_val_if_fail (data->file != NULL, -1);
- g_return_val_if_fail (data->list == NULL, -1);
- g_return_val_if_fail (data->final != NULL, -1);
+ g_return_val_if_fail (G_IS_FILE (file), NULL);
- gio_file = g_file_new_for_uri (data->file);
- g_file_load_contents_async (gio_file, data->cancellable, totem_cmml_read_file_result, data);
- return 0;
+ g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == totem_cmml_read_file);
+
+ if (g_simple_async_result_propagate_error (simple, error))
+ return NULL;
+
+ return g_simple_async_result_get_op_res_gpointer (simple);
}
static void
diff --git a/src/plugins/chapters/totem-cmml-parser.h b/src/plugins/chapters/totem-cmml-parser.h
index 649a29c..f5db15f 100644
--- a/src/plugins/chapters/totem-cmml-parser.h
+++ b/src/plugins/chapters/totem-cmml-parser.h
@@ -76,7 +76,14 @@ gchar * totem_cmml_convert_msecs_to_str (gint64 time_msecs);
TotemCmmlClip * totem_cmml_clip_new (const gchar *title, const gchar *desc, gint64 start, GdkPixbuf *pixbuf);
void totem_cmml_clip_free (TotemCmmlClip *clip);
TotemCmmlClip * totem_cmml_clip_copy (TotemCmmlClip *clip);
-gint totem_cmml_read_file_async (TotemCmmlAsyncData *data);
+
+void totem_cmml_read_file (GFile *file,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+GList *totem_cmml_read_file_finish (GFile *file,
+ GAsyncResult *res,
+ GError **error);
gint totem_cmml_write_file_async (TotemCmmlAsyncData *data);
#endif /* TOTEM_CMML_PARSER_H_ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]