[gupnp] Add gupnp_service_info_get_introspection_async_full()



commit da2e5c6ee053e366f2f6dc26d96af874e58f9e06
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 |   87 +++++++++++++++++++++++++++++++++++++++++
 libgupnp/gupnp-service-info.h |    7 +++
 2 files changed, 94 insertions(+), 0 deletions(-)
---
diff --git a/libgupnp/gupnp-service-info.c b/libgupnp/gupnp-service-info.c
index 1da6c19..a69d564 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,10 @@ 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 +659,12 @@ 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 +679,38 @@ 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 +727,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 +806,14 @@ gupnp_service_info_get_introspection_async
                                     data->message,
                                     (SoupSessionCallback) got_scpd_url,
                                     data);
+
+        data->cancellable = cancellable;
+        if (data->cancellable) {
+                g_object_ref (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]