[gupnp] Add gupnp_service_info_get_introspection_async_full()



commit 909e721c52a335aa8b0ef8f3c37fa62216451530
Author: Jussi Kukkonen <jussi kukkonen intel com>
Date:   Tue Dec 3 22:44:44 2013 +0200

    Add gupnp_service_info_get_introspection_async_full()
    
    This version of get_introspection can be cancelled using GCancellable.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=704867

 libgupnp/gupnp-service-info.c |   89 +++++++++++++++++++++++++++++++++++++++++
 libgupnp/gupnp-service-info.h |    7 +++
 2 files changed, 96 insertions(+), 0 deletions(-)
---
diff --git a/libgupnp/gupnp-service-info.c b/libgupnp/gupnp-service-info.c
index 1da6c19..8e0d1be 100644
--- a/libgupnp/gupnp-service-info.c
+++ b/libgupnp/gupnp-service-info.c
@@ -77,12 +77,18 @@ typedef struct {
         GUPnPServiceIntrospectionCallback callback;
         gpointer                          user_data;
 
+        GCancellable                     *cancellable;
+        gulong                            cancelled_id;
+
         SoupMessage                      *message;
 } GetSCPDURLData;
 
 static void
 get_scpd_url_data_free (GetSCPDURLData *data)
 {
+        if (data->cancellable) {
+            g_object_unref (data->cancellable);
+        }
         g_slice_free (GetSCPDURLData, data);
 }
 
@@ -187,6 +193,11 @@ gupnp_service_info_dispose (GObject *object)
 
                         data = info->priv->pending_gets->data;
 
+                        if (data->cancellable) {
+                            g_cancellable_disconnect (data->cancellable,
+                                                      data->cancelled_id);
+                        }
+
                         soup_session_cancel_message (session,
                                                      data->message,
                                                      SOUP_STATUS_CANCELLED);
@@ -649,6 +660,13 @@ got_scpd_url (G_GNUC_UNUSED SoupSession *session,
         } else
                 error = _gupnp_error_new_server_error (msg);
 
+        /* prevent the callback from canceling the cancellable
+         * (and so freeing data just before we do) */
+        if (data->cancellable) {
+            g_cancellable_disconnect (data->cancellable,
+                                      data->cancelled_id);
+        }
+
         data->info->priv->pending_gets =
                 g_list_remove (data->info->priv->pending_gets, data);
 
@@ -663,6 +681,39 @@ got_scpd_url (G_GNUC_UNUSED SoupSession *session,
         get_scpd_url_data_free (data);
 }
 
+static void
+cancellable_cancelled_cb (GCancellable *cancellable,
+                          gpointer user_data)
+{
+
+    GUPnPServiceInfo *info;
+    GetSCPDURLData *data;
+    SoupSession *session;
+    GError *error;
+
+    data = user_data;
+    info = data->info;
+
+    session = gupnp_context_get_session (info->priv->context);
+    soup_session_cancel_message (session,
+                                 data->message,
+                                 SOUP_STATUS_CANCELLED);
+
+    info->priv->pending_gets =
+            g_list_remove (info->priv->pending_gets, data);
+
+    error = g_error_new (G_IO_ERROR,
+                         G_IO_ERROR_CANCELLED,
+                         "The call was canceled");
+
+    data->callback (data->info,
+                    NULL,
+                    error,
+                    data->user_data);
+
+    get_scpd_url_data_free (data);
+}
+
 /**
  * gupnp_service_info_get_introspection_async:
  * @info: A #GUPnPServiceInfo
@@ -679,6 +730,35 @@ gupnp_service_info_get_introspection_async
                                  GUPnPServiceIntrospectionCallback callback,
                                  gpointer                          user_data)
 {
+    gupnp_service_info_get_introspection_async_full (info,
+                                                     callback,
+                                                     NULL,
+                                                     user_data);
+}
+
+/**
+ * gupnp_service_info_get_introspection_async_full:
+ * @info: A #GUPnPServiceInfo
+ * @callback: (scope async) : callback to be called when introspection object is ready.
+ * @cancellable: : GCancellable that can be used to cancel the call, or %NULL.
+ * @user_data: user_data to be passed to the callback.
+ *
+ * Note that introspection object is created from the information in service
+ * description document (SCPD) provided by the service so it can not be created
+ * if the service does not provide an SCPD.
+ *
+ * If @cancellable is used to cancel the call, @callback will be called with
+ * error code G_IO_ERROR_CANCELLED.
+ *
+ * Since: 0.20.10.
+ **/
+void
+gupnp_service_info_get_introspection_async_full
+                                (GUPnPServiceInfo                 *info,
+                                 GUPnPServiceIntrospectionCallback callback,
+                                 GCancellable                     *cancellable,
+                                 gpointer                          user_data)
+{
         GetSCPDURLData *data;
         char *scpd_url;
         SoupSession *session;
@@ -729,4 +809,13 @@ gupnp_service_info_get_introspection_async
                                     data->message,
                                     (SoupSessionCallback) got_scpd_url,
                                     data);
+
+        data->cancellable = g_object_ref (cancellable);
+        if (data->cancellable) {
+                data->cancelled_id = g_cancellable_connect
+                                (data->cancellable,
+                                 G_CALLBACK (cancellable_cancelled_cb),
+                                 data,
+                                 NULL);
+        }
 }
diff --git a/libgupnp/gupnp-service-info.h b/libgupnp/gupnp-service-info.h
index c81c29e..3fe2b3e 100644
--- a/libgupnp/gupnp-service-info.h
+++ b/libgupnp/gupnp-service-info.h
@@ -133,6 +133,13 @@ gupnp_service_info_get_introspection_async
                                GUPnPServiceIntrospectionCallback callback,
                                gpointer                          user_data);
 
+void
+gupnp_service_info_get_introspection_async_full
+                              (GUPnPServiceInfo                 *info,
+                               GUPnPServiceIntrospectionCallback callback,
+                               GCancellable                     *cancellable,
+                               gpointer                          user_data);
+
 G_END_DECLS
 
 #endif /* __GUPNP_SERVICE_INFO_H__ */


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