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 <[email protected]> --- 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 _______________________________________________ Spice-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/spice-devel
