[Spice-devel] [PATCH spice-gtk 5/8] usb-device-manager: Make spice_usb_device_manager_connect_device async
Hans de Goede
hdegoede at redhat.com
Wed Nov 16 09:49:48 PST 2011
With the (upcoming) introduction of the usb device node acl helper, which
uses policykit, spice_usbredir_channel_connect() may take a long time as
it will be waiting for the helper, which will be waiting for policykit which
may be interacting with the user. So spice_usbredir_channel_connect() will
need to become async, and since spice_usb_device_manager_connect_device
calls spice_usbredir_channel_connect it thus also needs to become async.
Note that this patch only changes spice_usb_device_manager_connect_device's
API to use the standard GIO async API, it is not actually async after this
patch since spice_usbredir_channel_connect is not yet async.
Signed-off-by: Hans de Goede <hdegoede at redhat.com>
---
gtk/Makefile.am | 2 +-
gtk/map-file | 3 +-
gtk/usb-device-manager.c | 110 ++++++++++++++++++++++++++++-----------
gtk/usb-device-manager.h | 13 ++++-
vapi/Makefile.am | 1 +
vapi/spice-client-glib-2.0.deps | 1 +
6 files changed, 94 insertions(+), 36 deletions(-)
create mode 100644 vapi/spice-client-glib-2.0.deps
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index a3960a7..17efc89 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -571,7 +571,7 @@ gtk_introspection_files = \
$(NULL)
SpiceClientGLib-2.0.gir: libspice-client-glib-2.0.la
-SpiceClientGLib_2_0_gir_INCLUDES = GObject-2.0
+SpiceClientGLib_2_0_gir_INCLUDES = GObject-2.0 Gio-2.0
SpiceClientGLib_2_0_gir_CFLAGS = $(SPICE_COMMON_CPPFLAGS)
SpiceClientGLib_2_0_gir_LIBS = libspice-client-glib-2.0.la
SpiceClientGLib_2_0_gir_FILES = $(glib_introspection_files)
diff --git a/gtk/map-file b/gtk/map-file
index f9bc46c..b6b84f1 100644
--- a/gtk/map-file
+++ b/gtk/map-file
@@ -87,7 +87,8 @@ spice_usb_device_manager_get_type;
spice_usb_device_manager_get;
spice_usb_device_manager_get_devices;
spice_usb_device_manager_is_device_connected;
-spice_usb_device_manager_connect_device;
+spice_usb_device_manager_connect_device_async;
+spice_usb_device_manager_connect_device_finish;
spice_usb_device_manager_disconnect_device;
spice_util_get_debug;
spice_util_get_version_string;
diff --git a/gtk/usb-device-manager.c b/gtk/usb-device-manager.c
index 2fb3dbb..9b02066 100644
--- a/gtk/usb-device-manager.c
+++ b/gtk/usb-device-manager.c
@@ -22,7 +22,6 @@
#include "config.h"
#include <glib-object.h>
-#include <gio/gio.h> /* For GInitable */
#include "glib-compat.h"
@@ -424,6 +423,27 @@ static gboolean spice_usb_device_manager_source_callback(gpointer user_data)
return TRUE;
}
+static void spice_usb_device_manager_auto_connect_cb(GObject *gobject,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ SpiceUsbDeviceManager *self = SPICE_USB_DEVICE_MANAGER(gobject);
+ SpiceUsbDevice *device = user_data;
+ GError *err = NULL;
+
+ spice_usb_device_manager_connect_device_finish(self, res, &err);
+ if (err) {
+ gchar *desc = spice_usb_device_get_description(device);
+ g_prefix_error(&err, "Could not auto-redirect %s: ", desc);
+ g_free(desc);
+
+ g_warning("%s", err->message);
+ g_signal_emit(self, signals[AUTO_CONNECT_FAILED], 0, device, err);
+ g_error_free(err);
+ }
+ g_object_unref(device);
+}
+
static void spice_usb_device_manager_dev_added(GUsbDeviceList *devlist,
GUsbDevice *_device,
GUdevDevice *udev,
@@ -436,17 +456,9 @@ static void spice_usb_device_manager_dev_added(GUsbDeviceList *devlist,
g_ptr_array_add(priv->devices, g_object_ref(device));
if (priv->auto_connect) {
- GError *err = NULL;
- spice_usb_device_manager_connect_device(manager, device, &err);
- if (err) {
- gchar *desc = spice_usb_device_get_description(device);
- g_prefix_error(&err, "Could not auto-redirect %s: ", desc);
- g_free(desc);
-
- g_warning("%s", err->message);
- g_signal_emit(manager, signals[AUTO_CONNECT_FAILED], 0, device, err);
- g_error_free(err);
- }
+ spice_usb_device_manager_connect_device_async(manager, device, NULL,
+ spice_usb_device_manager_auto_connect_cb,
+ g_object_ref(device));
}
SPICE_DEBUG("device added %p", device);
@@ -570,36 +582,47 @@ gboolean spice_usb_device_manager_is_device_connected(SpiceUsbDeviceManager *sel
}
/**
- * spice_usb_device_manager_connect_device:
+ * spice_usb_device_manager_connect_device_async:
* @manager: the #SpiceUsbDeviceManager manager
* @device: a #SpiceUsbDevice to redirect
- *
- * Returns: %TRUE if @device has been successfully connected and
- * associated with a redirection chanel
+ * @cancellable: a #GCancellable or NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to callback
*/
-gboolean spice_usb_device_manager_connect_device(SpiceUsbDeviceManager *self,
- SpiceUsbDevice *device, GError **err)
+void spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
+ SpiceUsbDevice *device,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
- g_return_val_if_fail(SPICE_IS_USB_DEVICE_MANAGER(self), FALSE);
- g_return_val_if_fail(device != NULL, FALSE);
- g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
+ GSimpleAsyncResult *result;
+
+ g_return_if_fail(SPICE_IS_USB_DEVICE_MANAGER(self));
+ g_return_if_fail(device != NULL);
SPICE_DEBUG("connecting device %p", device);
+ result = g_simple_async_result_new(G_OBJECT(self), callback, user_data,
+ spice_usb_device_manager_connect_device_async);
+
#ifdef USE_USBREDIR
SpiceUsbDeviceManagerPrivate *priv = self->priv;
+ GError *e = NULL;
guint i;
if (spice_usb_device_manager_is_device_connected(self, device)) {
- g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
+ g_simple_async_result_set_error(result,
+ SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
"Cannot connect an already connected usb device");
- return FALSE;
+ goto done;
}
if (!priv->source) {
- priv->source = g_usb_source_new(priv->main_context, priv->context, err);
- if (*err)
- return FALSE;
+ priv->source = g_usb_source_new(priv->main_context, priv->context, &e);
+ if (e) {
+ g_simple_async_result_take_error(result, e);
+ goto done;
+ }
g_usb_source_set_callback(priv->source,
spice_usb_device_manager_source_callback,
@@ -612,14 +635,39 @@ gboolean spice_usb_device_manager_connect_device(SpiceUsbDeviceManager *self,
if (spice_usbredir_channel_get_device(channel))
continue; /* Skip already used channels */
- return spice_usbredir_channel_connect(channel, priv->context,
- (GUsbDevice *)device, err);
+ if (!spice_usbredir_channel_connect(channel, priv->context,
+ (GUsbDevice *)device, &e)) {
+ g_simple_async_result_take_error(result, e);
+ goto done;
+ }
+
+ goto done;
}
#endif
- g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
- "No free USB channel");
- return FALSE;
+ g_simple_async_result_set_error(result,
+ SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
+ "No free USB channel");
+#ifdef USE_USBREDIR
+done:
+#endif
+ g_simple_async_result_complete_in_idle(result);
+ g_object_unref(result);
+}
+
+gboolean spice_usb_device_manager_connect_device_finish(
+ SpiceUsbDeviceManager *self, GAsyncResult *res, GError **err)
+{
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT(res);
+
+ g_return_val_if_fail(g_simple_async_result_is_valid(res, G_OBJECT(self),
+ spice_usb_device_manager_connect_device_async),
+ FALSE);
+
+ if (g_simple_async_result_propagate_error(simple, err))
+ return FALSE;
+
+ return TRUE;
}
/**
diff --git a/gtk/usb-device-manager.h b/gtk/usb-device-manager.h
index 00f8eb2..2417674 100644
--- a/gtk/usb-device-manager.h
+++ b/gtk/usb-device-manager.h
@@ -22,6 +22,7 @@
#define __SPICE_USB_DEVICE_MANAGER_H__
#include "spice-client.h"
+#include <gio/gio.h>
G_BEGIN_DECLS
@@ -96,9 +97,15 @@ GPtrArray *spice_usb_device_manager_get_devices(SpiceUsbDeviceManager *manager);
gboolean spice_usb_device_manager_is_device_connected(SpiceUsbDeviceManager *manager,
SpiceUsbDevice *device);
-gboolean spice_usb_device_manager_connect_device(SpiceUsbDeviceManager *manager,
- SpiceUsbDevice *device,
- GError **err);
+void spice_usb_device_manager_connect_device_async(
+ SpiceUsbDeviceManager *manager,
+ SpiceUsbDevice *device,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean spice_usb_device_manager_connect_device_finish(
+ SpiceUsbDeviceManager *self, GAsyncResult *res, GError **err);
+
void spice_usb_device_manager_disconnect_device(SpiceUsbDeviceManager *manager,
SpiceUsbDevice *device);
diff --git a/vapi/Makefile.am b/vapi/Makefile.am
index 87ffb8a..49f8509 100644
--- a/vapi/Makefile.am
+++ b/vapi/Makefile.am
@@ -4,6 +4,7 @@ if WITH_VALA
vapidir = $(datadir)/vala/vapi
vapi_DATA = \
spice-client-glib-2.0.vapi \
+ spice-client-glib-2.0.deps \
spice-client-gtk-$(SPICE_GTK_API_VERSION).deps \
spice-client-gtk-$(SPICE_GTK_API_VERSION).vapi \
$(NULL)
diff --git a/vapi/spice-client-glib-2.0.deps b/vapi/spice-client-glib-2.0.deps
new file mode 100644
index 0000000..cd10dfd
--- /dev/null
+++ b/vapi/spice-client-glib-2.0.deps
@@ -0,0 +1 @@
+gio-2.0
--
1.7.7.3
More information about the Spice-devel
mailing list