[Spice-devel] [PATCH spice-gtk 5/6] usbredir: Add a spice_usb_device_manager_can_redirect_device function
Hans de Goede
hdegoede at redhat.com
Wed Feb 22 08:28:25 PST 2012
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 at redhat.com>
---
gtk/map-file | 1 +
gtk/usb-device-manager.c | 71 ++++++++++++++++++++++++++++++---
gtk/usb-device-manager.h | 5 ++
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);
}
--
1.7.7.6
More information about the Spice-devel
mailing list