diff options
author | Hans de Goede <hdegoede@redhat.com> | 2012-02-21 11:50:03 +0100 |
---|---|---|
committer | Hans de Goede <hdegoede@redhat.com> | 2012-02-22 17:16:43 +0100 |
commit | e84b55a675bd5c25173194e4ee2518d9412d42f0 (patch) | |
tree | dcc489ff11d1af14390d2e094921adde152054d3 | |
parent | fdb494f7ece881485e473736b89ca48721e90e72 (diff) |
usbredir: Add a spice_usb_device_manager_can_redirect_device function
Add a spice_usb_device_manager_can_redirect_device function and use this
in SpiceUsbDeviceWidget to check if redirection is available.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-rw-r--r-- | gtk/map-file | 1 | ||||
-rw-r--r-- | gtk/usb-device-manager.c | 71 | ||||
-rw-r--r-- | gtk/usb-device-manager.h | 5 | ||||
-rw-r--r-- | gtk/usb-device-widget.c | 99 |
4 files changed, 144 insertions, 32 deletions
diff --git a/gtk/map-file b/gtk/map-file index 320dae3..81cd682 100644 --- a/gtk/map-file +++ b/gtk/map-file @@ -85,6 +85,7 @@ spice_smartcard_reader_get_type; spice_smartcard_reader_is_software; spice_usb_device_get_description; spice_usb_device_get_type; +spice_usb_device_manager_can_redirect_device; spice_usb_device_manager_connect_device_async; spice_usb_device_manager_connect_device_finish; spice_usb_device_manager_disconnect_device; diff --git a/gtk/usb-device-manager.c b/gtk/usb-device-manager.c index dea0ab5..959e0ab 100644 --- a/gtk/usb-device-manager.c +++ b/gtk/usb-device-manager.c @@ -212,7 +212,7 @@ static gboolean spice_usb_device_manager_initable_init(GInitable *initable, return TRUE; #else g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, - "USB redirection support not compiled in"); + _("USB redirection support not compiled in")); return FALSE; #endif } @@ -578,10 +578,17 @@ static void spice_usb_device_manager_add_dev(SpiceUsbDeviceManager *self, g_ptr_array_add(priv->devices, device); if (priv->auto_connect) { - if (usbredirhost_check_device_filter( - priv->auto_conn_filter_rules, - priv->auto_conn_filter_rules_count, - device, 0) == 0) + gboolean can_redirect, auto_ok; + + can_redirect = spice_usb_device_manager_can_redirect_device( + self, (SpiceUsbDevice *)device, NULL); + + auto_ok = usbredirhost_check_device_filter( + priv->auto_conn_filter_rules, + priv->auto_conn_filter_rules_count, + device, 0) == 0; + + if (can_redirect && auto_ok) spice_usb_device_manager_connect_device_async(self, (SpiceUsbDevice *)device, NULL, spice_usb_device_manager_auto_connect_cb, @@ -861,7 +868,7 @@ void spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self, g_simple_async_result_set_error(result, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, - "No free USB channel"); + _("No free USB channel")); #ifdef USE_USBREDIR done: #endif @@ -908,6 +915,58 @@ void spice_usb_device_manager_disconnect_device(SpiceUsbDeviceManager *self, #endif } +gboolean +spice_usb_device_manager_can_redirect_device(SpiceUsbDeviceManager *self, + SpiceUsbDevice *device, + GError **err) +{ +#ifdef USE_USBREDIR + SpiceUsbDeviceManagerPrivate *priv = self->priv; + int i; + gboolean enabled; + + 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); + + g_object_get(G_OBJECT(priv->session), "enable-usbredir", &enabled, NULL); + if (!enabled) { + g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + _("USB redirection is disabled")); + return FALSE; + } + + if (!priv->channels->len) { + g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + _("The connected VM is not configured for USB redirection")); + return FALSE; + } + + /* Skip the other checks for already connected devices */ + if (spice_usb_device_manager_is_device_connected(self, device)) + return TRUE; + + /* Check if there are free channels */ + for (i = 0; i < priv->channels->len; i++) { + SpiceUsbredirChannel *channel = g_ptr_array_index(priv->channels, i); + + if (!spice_usbredir_channel_get_device(channel)) + break; + } + if (i == priv->channels->len) { + g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + _("There are no free USB channels")); + return FALSE; + } + + return TRUE; +#else + g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + _("USB redirection support not compiled in")); + return FALSE; +#endif +} + /** * spice_usb_device_get_description: * @device: #SpiceUsbDevice to get the description of diff --git a/gtk/usb-device-manager.h b/gtk/usb-device-manager.h index eabfd00..de0e2ba 100644 --- a/gtk/usb-device-manager.h +++ b/gtk/usb-device-manager.h @@ -110,6 +110,11 @@ gboolean spice_usb_device_manager_connect_device_finish( void spice_usb_device_manager_disconnect_device(SpiceUsbDeviceManager *manager, SpiceUsbDevice *device); +gboolean +spice_usb_device_manager_can_redirect_device(SpiceUsbDeviceManager *self, + SpiceUsbDevice *device, + GError **err); + G_END_DECLS #endif /* __SPICE_USB_DEVICE_MANAGER_H__ */ diff --git a/gtk/usb-device-widget.c b/gtk/usb-device-widget.c index 1bfffc0..faaeace 100644 --- a/gtk/usb-device-widget.c +++ b/gtk/usb-device-widget.c @@ -71,6 +71,7 @@ struct _SpiceUsbDeviceWidgetPrivate { gchar *device_format_string; SpiceUsbDeviceManager *manager; GtkWidget *info_bar; + gchar *err_msg; }; static guint signals[LAST_SIGNAL] = { 0, }; @@ -167,11 +168,9 @@ static GObject *spice_usb_device_widget_constructor( GObject *obj; SpiceUsbDeviceWidget *self; SpiceUsbDeviceWidgetPrivate *priv; - const gchar *err_msg = NULL; GPtrArray *devices = NULL; GError *err = NULL; GtkWidget *label; - gboolean enabled; gchar *str; int i; @@ -187,28 +186,6 @@ static GObject *spice_usb_device_widget_constructor( if (!priv->session) g_error("SpiceUsbDeviceWidget constructed without a session"); - g_object_get(G_OBJECT(priv->session), "enable-usbredir", &enabled, NULL); - if (!enabled) - err_msg = _("USB redirection is disabled"); - - if (!err_msg && !spice_session_has_channel_type(priv->session, - SPICE_CHANNEL_USBREDIR)) - err_msg = _("The connected VM is not configured for USB redirection"); - - if (!err_msg) { - priv->manager = spice_usb_device_manager_get(priv->session, &err); - if (!err) { - g_signal_connect(priv->manager, "device-added", - G_CALLBACK(device_added_cb), self); - g_signal_connect(priv->manager, "device-removed", - G_CALLBACK(device_removed_cb), self); - g_signal_connect(priv->manager, "device-error", - G_CALLBACK(device_error_cb), self); - devices = spice_usb_device_manager_get_devices(priv->manager); - } else - err_msg = err->message; - } - label = gtk_label_new(NULL); str = g_strdup_printf("<b>%s</b>", _("Select USB devices to redirect")); gtk_label_set_markup(GTK_LABEL (label), str); @@ -216,14 +193,24 @@ static GObject *spice_usb_device_widget_constructor( gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_box_pack_start(GTK_BOX(self), label, FALSE, FALSE, 0); - if (err_msg) { - spice_usb_device_widget_show_info_bar(self, err_msg, + priv->manager = spice_usb_device_manager_get(priv->session, &err); + if (err) { + spice_usb_device_widget_show_info_bar(self, err->message, GTK_MESSAGE_WARNING, GTK_STOCK_DIALOG_WARNING); g_clear_error(&err); return obj; } + g_signal_connect(priv->manager, "device-added", + G_CALLBACK(device_added_cb), self); + g_signal_connect(priv->manager, "device-removed", + G_CALLBACK(device_removed_cb), self); + g_signal_connect(priv->manager, "device-error", + G_CALLBACK(device_error_cb), self); + + devices = spice_usb_device_manager_get_devices(priv->manager); + for (i = 0; i < devices->len; i++) device_added_cb(NULL, g_ptr_array_index(devices, i), self); @@ -351,6 +338,60 @@ static SpiceUsbDevice *get_usb_device(GtkWidget *widget) return g_object_get_data(G_OBJECT(widget), "usb-device"); } +static void check_can_redirect(GtkWidget *widget, gpointer user_data) +{ + SpiceUsbDeviceWidget *self = SPICE_USB_DEVICE_WIDGET(user_data); + SpiceUsbDeviceWidgetPrivate *priv = self->priv; + SpiceUsbDevice *device; + gboolean can_redirect; + GError *err = NULL; + + device = get_usb_device(widget); + if (!device) + return; /* Non device widget, ie the info_bar */ + + can_redirect = spice_usb_device_manager_can_redirect_device(priv->manager, + device, &err); + gtk_widget_set_sensitive(widget, can_redirect); + + /* If we can not redirect this device, append the error message to + err_msg, but only if it is *not* already there! */ + if (!can_redirect) { + if (priv->err_msg) { + if (!strstr(priv->err_msg, err->message)) { + gchar *old_err_msg = priv->err_msg; + + priv->err_msg = g_strdup_printf("%s\n%s", priv->err_msg, + err->message); + g_free(old_err_msg); + } + } else { + priv->err_msg = g_strdup(err->message); + } + } + + g_clear_error(&err); +} + +static gboolean spice_usb_device_widget_update_status(gpointer user_data) +{ + SpiceUsbDeviceWidget *self = SPICE_USB_DEVICE_WIDGET(user_data); + SpiceUsbDeviceWidgetPrivate *priv = self->priv; + + gtk_container_foreach(GTK_CONTAINER(self), check_can_redirect, self); + + if (priv->err_msg) { + spice_usb_device_widget_show_info_bar(self, priv->err_msg, + GTK_MESSAGE_INFO, + GTK_STOCK_DIALOG_WARNING); + g_free(priv->err_msg); + priv->err_msg = NULL; + } else { + spice_usb_device_widget_hide_info_bar(self); + } + return FALSE; +} + typedef struct _connect_cb_data { GtkWidget *check; SpiceUsbDeviceWidget *self; @@ -379,6 +420,7 @@ static void connect_cb(GObject *gobject, GAsyncResult *res, gpointer user_data) g_error_free(err); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->check), FALSE); + spice_usb_device_widget_update_status(self); } g_object_unref(data->check); @@ -407,6 +449,7 @@ static void checkbox_clicked_cb(GtkWidget *check, gpointer user_data) spice_usb_device_manager_disconnect_device(priv->manager, device); } + spice_usb_device_widget_update_status(self); } static void checkbox_usb_device_destroy_notify(gpointer data) @@ -459,6 +502,8 @@ static void device_removed_cb(SpiceUsbDeviceManager *manager, gtk_container_foreach(GTK_CONTAINER(self), destroy_widget_by_usb_device, device); + + spice_usb_device_widget_update_status(self); } static void set_inactive_by_usb_device(GtkWidget *widget, gpointer user_data) @@ -474,4 +519,6 @@ static void device_error_cb(SpiceUsbDeviceManager *manager, gtk_container_foreach(GTK_CONTAINER(self), set_inactive_by_usb_device, device); + + spice_usb_device_widget_update_status(self); } |