[grilo] core: Make resolve() a cancellable operation



commit 97c9bd000ffc4d75c6707f793ee4bfaf201058a0
Author: Juan A. Suarez Romero <jasuarez igalia com>
Date:   Wed Apr 6 06:42:57 2011 +0000

    core: Make resolve() a cancellable operation
    
    Fixes https://bugzilla.gnome.org/show_bug.cgi?id=644383
    
    Signed-off-by: Juan A. Suarez Romero <jasuarez igalia com>

 src/grl-media-source.c    |    6 +++-
 src/grl-metadata-source.c |   48 +++++++++++++++++++++++++++++++++++++-------
 src/grl-metadata-source.h |   18 ++++++++++------
 3 files changed, 55 insertions(+), 17 deletions(-)
---
diff --git a/src/grl-media-source.c b/src/grl-media-source.c
index e8444c1..5693743 100644
--- a/src/grl-media-source.c
+++ b/src/grl-media-source.c
@@ -978,6 +978,7 @@ full_resolution_check_waiting_list (GList **waiting_list,
 
 static void
 full_resolution_done_cb (GrlMetadataSource *source,
+                         guint resolve_id,
 			 GrlMedia *media,
 			 gpointer user_data,
 			 const GError *error)
@@ -1116,7 +1117,7 @@ full_resolution_ctl_cb (GrlMediaSource *source,
        full_resolution_done_cb, so we fake the resolution to get into that
        callback */
     done_info->pending_callbacks = 1;
-    full_resolution_done_cb (NULL, media, done_info, error);
+    full_resolution_done_cb (NULL, 0, media, done_info, error);
   } else {
     GList *sources, *iter;
     /* Start full-resolution: save all the data we need to emit the result
@@ -1153,13 +1154,14 @@ full_resolution_ctl_cb (GrlMediaSource *source,
 
     if (!done_info->pending_callbacks) {
       done_info->pending_callbacks = 1;
-      full_resolution_done_cb (NULL, media, done_info, NULL);
+      full_resolution_done_cb (NULL, 0, media, done_info, NULL);
     }
   }
 }
 
 static void
 metadata_full_resolution_done_cb (GrlMetadataSource *source,
+                                  guint operation_id,
 				  GrlMedia *media,
 				  gpointer user_data,
 				  const GError *error)
diff --git a/src/grl-metadata-source.c b/src/grl-metadata-source.c
index ebac1a4..568f7e5 100644
--- a/src/grl-metadata-source.c
+++ b/src/grl-metadata-source.c
@@ -350,16 +350,37 @@ set_metadata_ctl_cb (GrlMetadataSource *source,
 
 static void
 resolve_result_relay_cb (GrlMetadataSource *source,
+                         guint resolve_id,
 			 GrlMedia *media,
 			 gpointer user_data,
 			 const GError *error)
 {
+  gboolean should_free_error = FALSE;
+  GError *_error = (GError *) error;
+
   GRL_DEBUG ("resolve_result_relay_cb");
 
   struct ResolveRelayCb *rrc;
 
   rrc = (struct ResolveRelayCb *) user_data;
-  rrc->user_callback (source, media, rrc->user_data, error);
+
+  if (grl_metadata_source_operation_is_cancelled (source,
+                                                  rrc->spec->resolve_id)) {
+    /* if the plugin already set an error, we don't care because we're
+     * cancelled */
+    _error = g_error_new (GRL_CORE_ERROR, GRL_CORE_ERROR_OPERATION_CANCELLED,
+                          "Operation was cancelled");
+    /* yet, we should free the error we just created (if we didn't create it,
+     * the plugin owns it) */
+    should_free_error = TRUE;
+  }
+
+  rrc->user_callback (source, rrc->spec->resolve_id, media,
+                      rrc->user_data, _error);
+
+  if (should_free_error && _error) {
+    g_error_free (_error);
+  }
 
   g_object_unref (rrc->spec->source);
   g_object_unref (rrc->spec->media);
@@ -380,6 +401,7 @@ resolve_idle (gpointer user_data)
 
 static void
 resolve_result_async_cb (GrlMetadataSource *source,
+                         guint resolve_id,
                          GrlMedia *media,
                          gpointer user_data,
                          const GError *error)
@@ -888,11 +910,13 @@ grl_metadata_source_may_resolve (GrlMetadataSource *source,
  * This is the main method of the #GrlMetadataSource class. It will fetch the
  * metadata of the requested keys.
  *
- * This function is asynchronous and uses the Glib's main loop.
+ * This function is asynchronous.
+ *
+ * Returns: the operation identifier
  *
  * Since: 0.1.4
  */
-void
+guint
 grl_metadata_source_resolve (GrlMetadataSource *source,
                              const GList *keys,
                              GrlMedia *media,
@@ -903,14 +927,15 @@ grl_metadata_source_resolve (GrlMetadataSource *source,
   GrlMetadataSourceResolveSpec *rs;
   GList *_keys;
   struct ResolveRelayCb *rrc;
+  guint resolve_id;
 
   GRL_DEBUG ("grl_metadata_source_resolve");
 
-  g_return_if_fail (GRL_IS_METADATA_SOURCE (source));
-  g_return_if_fail (callback != NULL);
-  g_return_if_fail (media != NULL);
-  g_return_if_fail (grl_metadata_source_supported_operations (source) &
-                    GRL_OP_RESOLVE);
+  g_return_val_if_fail (GRL_IS_METADATA_SOURCE (source), 0);
+  g_return_val_if_fail (callback != NULL, 0);
+  g_return_val_if_fail (media != NULL, 0);
+  g_return_val_if_fail (grl_metadata_source_supported_operations (source) &
+                        GRL_OP_RESOLVE, 0);
 
   _keys = g_list_copy ((GList *) keys);
 
@@ -918,6 +943,9 @@ grl_metadata_source_resolve (GrlMetadataSource *source,
     grl_metadata_source_filter_slow (source, &_keys, FALSE);
   }
 
+  resolve_id =
+    grl_metadata_source_gen_operation_id (GRL_METADATA_SOURCE (source));
+
   /* Always hook an own relay callback so we can do some
      post-processing before handing out the results
      to the user */
@@ -927,6 +955,7 @@ grl_metadata_source_resolve (GrlMetadataSource *source,
 
   rs = g_new0 (GrlMetadataSourceResolveSpec, 1);
   rs->source = g_object_ref (source);
+  rs->resolve_id = resolve_id;
   rs->keys = _keys;
   rs->media = g_object_ref (media);
   rs->flags = flags;
@@ -937,11 +966,14 @@ grl_metadata_source_resolve (GrlMetadataSource *source,
      user_data so that we can free the spec there */
   rrc->spec = rs;
 
+  grl_metadata_source_set_operation_ongoing (source, resolve_id);
   g_idle_add_full (flags & GRL_RESOLVE_IDLE_RELAY?
                    G_PRIORITY_DEFAULT_IDLE: G_PRIORITY_HIGH_IDLE,
                    resolve_idle,
                    rs,
                    NULL);
+
+  return resolve_id;
 }
 
 /**
diff --git a/src/grl-metadata-source.h b/src/grl-metadata-source.h
index d20b4d9..5638813 100644
--- a/src/grl-metadata-source.h
+++ b/src/grl-metadata-source.h
@@ -111,6 +111,7 @@ struct _GrlMetadataSource {
 /**
  * GrlMetadataSourceResolveCb:
  * @source: a metadata source
+ * @operation_id: operation identifier
  * @media: (transfer full): a #GrlMedia transfer object
  * @user_data: user data passed to grl_metadata_source_resolve()
  * @error: (type uint): possible #GError generated when resolving the metadata
@@ -118,6 +119,7 @@ struct _GrlMetadataSource {
  * Prototype for the callback passed to grl_metadata_source_resolve()
  */
 typedef void (*GrlMetadataSourceResolveCb) (GrlMetadataSource *source,
+                                            guint operation_id,
                                             GrlMedia *media,
                                             gpointer user_data,
                                             const GError *error);
@@ -144,6 +146,7 @@ typedef void (*GrlMetadataSourceSetMetadataCb) (GrlMetadataSource *source,
 /**
  * GrlMetadataSourceResolveSpec:
  * @source: a metadata source
+ * @resolve_id: operation identifier
  * @keys: the #GList of #GrlKeyID to fetch and store
  * @media: a #GrlMedia transfer object
  * @flags: bitwise mask of #GrlMetadataResolutionFlags with the resolution
@@ -156,6 +159,7 @@ typedef void (*GrlMetadataSourceSetMetadataCb) (GrlMetadataSource *source,
  */
 typedef struct {
   GrlMetadataSource *source;
+  guint resolve_id;
   GList *keys;
   GrlMedia *media;
   GrlMetadataResolutionFlags flags;
@@ -163,7 +167,7 @@ typedef struct {
   gpointer user_data;
 
   /*< private >*/
-  gpointer _grl_reserved[GRL_PADDING];
+  gpointer _grl_reserved[GRL_PADDING - 1];
 } GrlMetadataSourceResolveSpec;
 
 /**
@@ -313,12 +317,12 @@ gboolean grl_metadata_source_may_resolve (GrlMetadataSource *source,
                                           GrlKeyID key_id,
                                           GList **missing_keys);
 
-void grl_metadata_source_resolve (GrlMetadataSource *source,
-                                  const GList *keys,
-                                  GrlMedia *media,
-                                  GrlMetadataResolutionFlags flags,
-                                  GrlMetadataSourceResolveCb callback,
-                                  gpointer user_data);
+guint grl_metadata_source_resolve (GrlMetadataSource *source,
+                                   const GList *keys,
+                                   GrlMedia *media,
+                                   GrlMetadataResolutionFlags flags,
+                                   GrlMetadataSourceResolveCb callback,
+                                   gpointer user_data);
 
 GrlMedia *grl_metadata_source_resolve_sync (GrlMetadataSource *source,
                                             const GList *keys,



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