[Spice-commits] 6 commits - src/map-file src/spice-option.c src/usb-device-manager.c src/usb-device-manager.h src/usb-device-widget.c

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Sat Feb 1 11:53:07 UTC 2020


 src/map-file             |    3 
 src/spice-option.c       |   28 +++++++++
 src/usb-device-manager.c |  142 ++++++++++++++++++++++++++++++++++++++++++++---
 src/usb-device-manager.h |   12 +++
 src/usb-device-widget.c  |   78 ++++++++++++++++++++++++-
 5 files changed, 251 insertions(+), 12 deletions(-)

New commits:
commit fc67c4265671dc808d08385cd8dc1a515505e207
Author: Alexander Nezhinsky <anezhins at redhat.com>
Date:   Thu Jan 2 17:09:16 2020 +0200

    fix check widget identification in usb-device-widget::set_inactive_by_usb_device()
    
    check widget was identified by taking the child of the passed widget
    but the check widget itself is being passed
    
    Acked-by: Frediano Ziglio <fziglio at redhat.com>

diff --git a/src/usb-device-widget.c b/src/usb-device-widget.c
index 3a33091..9898083 100644
--- a/src/usb-device-widget.c
+++ b/src/usb-device-widget.c
@@ -653,10 +653,9 @@ static void device_removed_cb(SpiceUsbDeviceManager *manager,
     spice_usb_device_widget_update_status(self);
 }
 
-static void set_inactive_by_usb_device(GtkWidget *widget, gpointer user_data)
+static void set_inactive_by_usb_device(GtkWidget *check, gpointer user_data)
 {
-    if (get_usb_device(widget) == user_data) {
-        GtkWidget *check = gtk_bin_get_child(GTK_BIN(widget));
+    if (get_usb_device(check) == user_data) {
         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), FALSE);
     }
 }
commit c4c7eb34c4e04fc6c65e6de75695f2e9de45ffd1
Author: Alexander Nezhinsky <anezhins at redhat.com>
Date:   Thu Jan 2 17:08:41 2020 +0200

    remove shared cd in usb-dev-manager on any disconnect event
    
    When a shared cd fails to connect, experiences a device error
    or gets disconnected, its device should be removed to avoid the
    'existing but not connected' state, which is disallowed for cd devices.
    
    Acked-by: Frediano Ziglio <fziglio at redhat.com>

diff --git a/src/usb-device-manager.c b/src/usb-device-manager.c
index 4fb2087..066b92e 100644
--- a/src/usb-device-manager.c
+++ b/src/usb-device-manager.c
@@ -938,6 +938,26 @@ static void spice_usb_device_manager_check_redir_on_connect(SpiceUsbDeviceManage
     }
 }
 
+static void
+spice_usb_device_manager_handle_disconnect(SpiceUsbDeviceManager *manager,
+                                           SpiceUsbDevice *device)
+{
+    if (spice_usb_device_manager_is_device_shared_cd(manager, device)) {
+        GError *err = NULL;
+        gboolean rc;
+
+        rc = spice_usb_device_manager_remove_shared_cd_device(manager, device, &err);
+        if (!rc) {
+            if (err) {
+                SPICE_DEBUG("Failed to remove cd device, %s", err->message);
+                g_error_free(err);
+            } else {
+                SPICE_DEBUG("Failed to remove cd device");
+            }
+        }
+    }
+}
+
 void spice_usb_device_manager_device_error(SpiceUsbDeviceManager *manager,
                                            SpiceUsbDevice *device,
                                            GError *err)
@@ -946,6 +966,7 @@ void spice_usb_device_manager_device_error(SpiceUsbDeviceManager *manager,
     g_return_if_fail(device != NULL);
 
     g_signal_emit(manager, signals[DEVICE_ERROR], 0, device, err);
+    spice_usb_device_manager_handle_disconnect(manager, device);
 }
 #endif
 
@@ -1151,8 +1172,9 @@ void spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *manage
 
 #ifdef USE_USBREDIR
 
-    GTask *task =
-        g_task_new(G_OBJECT(manager), cancellable, callback, user_data);
+    GTask *task = g_task_new(G_OBJECT(manager), cancellable, callback, user_data);
+
+    g_task_set_task_data(task, device, NULL);
 
     _set_redirecting(manager, TRUE);
     _spice_usb_device_manager_connect_device_async(manager, device,
@@ -1213,13 +1235,19 @@ void _connect_device_async_cb(GObject *gobject,
 {
     SpiceUsbDeviceManager *manager = SPICE_USB_DEVICE_MANAGER(gobject);
     GTask *task = user_data;
-    GError *error = NULL;
+    GError *err = NULL;
+    gboolean rc;
 
     _set_redirecting(manager, FALSE);
-    if (_spice_usb_device_manager_connect_device_finish(manager, channel_res, &error)) {
+
+    rc = _spice_usb_device_manager_connect_device_finish(manager, channel_res, &err);
+    if (rc) {
         g_task_return_boolean(task, TRUE);
     } else {
-        g_task_return_error(task, error);
+        SpiceUsbDevice *device = g_task_get_task_data(task);
+
+        spice_usb_device_manager_handle_disconnect(manager, device);
+        g_task_return_error(task, err);
     }
     g_object_unref(task);
 }
@@ -1265,8 +1293,9 @@ void _disconnect_device_async_cb(GObject *gobject,
 {
     SpiceUsbredirChannel *channel = SPICE_USBREDIR_CHANNEL(gobject);
     GTask *task = user_data;
-    GError *err = NULL;
     SpiceUsbDeviceManager *manager = SPICE_USB_DEVICE_MANAGER(g_task_get_source_object(task));
+    SpiceUsbDevice *device = g_task_get_task_data(task);
+    GError *err = NULL;
 
     _set_redirecting(manager, FALSE);
 
@@ -1275,6 +1304,8 @@ void _disconnect_device_async_cb(GObject *gobject,
         g_task_return_error(task, err);
     } else {
         g_task_return_boolean(task, TRUE);
+
+        spice_usb_device_manager_handle_disconnect(manager, device);
     }
 
     g_object_unref(task);
@@ -1316,6 +1347,7 @@ void spice_usb_device_manager_disconnect_device_async(SpiceUsbDeviceManager *man
 
     channel = spice_usb_device_manager_get_channel_for_dev(manager, device);
     nested  = g_task_new(G_OBJECT(manager), cancellable, callback, user_data);
+    g_task_set_task_data(nested, device, NULL);
 
     spice_usbredir_channel_disconnect_device_async(channel, cancellable,
                                                    _disconnect_device_async_cb,
commit 33f7e09ef07c9c9230c602d8b4956e4ff9613427
Author: Alexander Nezhinsky <anezhins at redhat.com>
Date:   Thu Nov 21 15:47:56 2019 +0200

    auto-connect shared CD devices added using command line
    
    Shared CD devices have special lifecycle requirements: they are always
    auto-redirected after being created and always destroyed after being
    disconnected. Thus the intermediate state of an existing but not connected
    device, which is normal for the physical devices, is not supported.
    
    For the devices added using the corresponding command line options it
    means that they should be auto-connected on the viewer start.
    By default such devices are redirected subject to the 'redirect-on-connect'
    filter, which does not fit the shared CD connecting requirements above.
    Instead, CDs are redirected unconditionally by this patch.
    
    Acked-by: Frediano Ziglio <fziglio at redhat.com>

diff --git a/src/usb-device-manager.c b/src/usb-device-manager.c
index 9b7e538..4fb2087 100644
--- a/src/usb-device-manager.c
+++ b/src/usb-device-manager.c
@@ -894,6 +894,7 @@ static void spice_usb_device_manager_check_redir_on_connect(SpiceUsbDeviceManage
     SpiceUsbDeviceManagerPrivate *priv = manager->priv;
     GTask *task;
     SpiceUsbDevice *device;
+    gboolean is_cd, shall_redirect;
     guint i;
 
     if (priv->redirect_on_connect == NULL) {
@@ -907,9 +908,20 @@ static void spice_usb_device_manager_check_redir_on_connect(SpiceUsbDeviceManage
             continue;
         }
 
-        if (spice_usb_backend_device_check_filter(device,
-                                                  priv->redirect_on_connect_rules,
-                                                  priv->redirect_on_connect_rules_count) == 0) {
+        is_cd = spice_usb_device_manager_is_device_shared_cd(manager, device);
+
+        if (is_cd) {
+            shall_redirect = TRUE;
+        } else if (priv->redirect_on_connect) {
+            const struct usbredirfilter_rule *rules = priv->redirect_on_connect_rules;
+            int rules_count = priv->redirect_on_connect_rules_count;
+
+            shall_redirect = !spice_usb_backend_device_check_filter(device, rules, rules_count);
+        } else {
+            shall_redirect = FALSE;
+        }
+
+        if (shall_redirect) {
             /* Note: re-uses spice_usb_device_manager_connect_device_async's
                completion handling code! */
             task = g_task_new(manager,
commit 37433379bd703c62b1e1ec98bfbab4c77490b95f
Author: Alexander Nezhinsky <anezhins at redhat.com>
Date:   Tue Nov 12 15:13:38 2019 +0200

    Add --spice-share-cd command line option
    
    Acked-by: Frediano Ziglio <fziglio at redhat.com>

diff --git a/src/spice-option.c b/src/spice-option.c
index 8c4e707..6237bc9 100644
--- a/src/spice-option.c
+++ b/src/spice-option.c
@@ -39,6 +39,7 @@ static gint cache_size = 0;
 static gint glz_window_size = 0;
 static gchar *secure_channels = NULL;
 static gchar *shared_dir = NULL;
+static gchar **cd_share_files = NULL;
 static SpiceImageCompression preferred_compression = SPICE_IMAGE_COMPRESSION_INVALID;
 
 G_GNUC_NORETURN
@@ -183,6 +184,8 @@ GOptionGroup* spice_get_option_group(void)
           N_("Filter selecting USB devices to be auto-redirected when plugged in"), N_("<filter-string>") },
         { "spice-usbredir-redirect-on-connect", '\0', 0, G_OPTION_ARG_STRING, &usbredir_redirect_on_connect,
           N_("Filter selecting USB devices to redirect on connect"), N_("<filter-string>") },
+        { "spice-share-cd", '\0', 0, G_OPTION_ARG_STRING_ARRAY, &cd_share_files,
+          N_("Name of ISO file or CD/DVD device to share"), N_("<filename> (repeat allowed)") },
         { "spice-cache-size", '\0', 0, G_OPTION_ARG_INT, &cache_size,
           N_("Image cache size (deprecated)"), N_("<bytes>") },
         { "spice-glz-window-size", '\0', 0, G_OPTION_ARG_INT, &glz_window_size,
@@ -288,6 +291,31 @@ void spice_set_session_option(SpiceSession *session)
                          usbredir_redirect_on_connect, NULL);
         }
     }
+    if (cd_share_files) {
+        SpiceUsbDeviceManager *m =
+                get_usb_device_manager_for_option(session, "--spice-share-cd");
+        if (m) {
+            gchar **name = cd_share_files;
+            GError *err = NULL;
+            gboolean rc;
+
+            while (name && *name) {
+                rc = spice_usb_device_manager_create_shared_cd_device(m, *name, &err);
+                if (!rc) {
+                    if (err == NULL) {
+                        g_warning("Failed to create shared CD device %s", *name);
+                    } else {
+                        g_warning("Failed to create shared CD device %s: %s",
+                                  *name, err->message);
+                        g_clear_error(&err);
+                    }
+                }
+                name++;
+            }
+        }
+        g_strfreev(cd_share_files);
+        cd_share_files = NULL;
+    }
     if (disable_usbredir)
         g_object_set(session, "enable-usbredir", FALSE, NULL);
     if (disable_audio)
commit 7a9076266b0c0bde9094663469820d462c973d61
Author: Alexander Nezhinsky <anezhins at redhat.com>
Date:   Tue Nov 19 13:30:30 2019 +0200

    Add empty CD entry to usb-device-widget, create shared CD when toggled
    
    The empty CD entry is a placeholder and appears every time the widget is created.
    When it is toggled, a file chooser dialog is popped up. If a file or device is
    selected, a new CD device is created. The new CD device is auto-connected.
    
    This device is communicated to the widget through the 'device-added' signal.
    The list entry responsible for the new device corresponds to the entity
    provided by usb-device-manager. The empty CD entry is automatically moved to
    the top of the list.
    
    Acked-by: Frediano Ziglio <fziglio at redhat.com>

diff --git a/src/usb-device-widget.c b/src/usb-device-widget.c
index b09940d..3a33091 100644
--- a/src/usb-device-widget.c
+++ b/src/usb-device-widget.c
@@ -24,6 +24,7 @@
 #include "spice-client.h"
 #include "spice-marshal.h"
 #include "usb-device-widget.h"
+#include "usb-device-manager.h"
 
 /**
  * SECTION:usb-device-widget
@@ -62,6 +63,8 @@ static void device_removed_cb(SpiceUsbDeviceManager *manager, SpiceUsbDevice *de
                               gpointer user_data);
 static void device_error_cb(SpiceUsbDeviceManager *manager, SpiceUsbDevice *device,
                             GError *err, gpointer user_data);
+static void empty_cd_clicked_cb(GtkToggleButton *toggle, gpointer user_data);
+
 static gboolean spice_usb_device_widget_update_status(gpointer user_data);
 
 enum {
@@ -79,6 +82,7 @@ struct _SpiceUsbDeviceWidgetPrivate {
     SpiceSession *session;
     gchar *device_format_string;
     SpiceUsbDeviceManager *manager;
+    GtkWidget *empty_cd;
     GtkWidget *info_bar;
     GtkWidget *label;
     gchar *err_msg;
@@ -189,6 +193,64 @@ spice_usb_device_widget_show_info_bar(SpiceUsbDeviceWidget *self,
     gtk_widget_show_all(priv->info_bar);
 }
 
+static void
+empty_cd_clicked_cb(GtkToggleButton *toggle, gpointer user_data)
+{
+    SpiceUsbDeviceWidget *self = SPICE_USB_DEVICE_WIDGET(user_data);
+    SpiceUsbDeviceWidgetPrivate *priv = self->priv;
+    GtkWidget *dialog;
+    gint dialog_rc;
+
+    if (!gtk_toggle_button_get_active(toggle)) {
+        return;
+    }
+    gtk_toggle_button_set_active(toggle, FALSE);
+
+    dialog = gtk_file_chooser_dialog_new(_("Select ISO file or device"),
+                                         GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(self))),
+                                         GTK_FILE_CHOOSER_ACTION_OPEN,
+                                         _("_Cancel"), GTK_RESPONSE_CANCEL,
+                                         _("_Open"), GTK_RESPONSE_ACCEPT,
+                                         NULL);
+
+    dialog_rc = gtk_dialog_run(GTK_DIALOG(dialog));
+    if (dialog_rc == GTK_RESPONSE_ACCEPT) {
+        gchar *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
+        GError *err = NULL;
+        gboolean rc;
+
+        rc = spice_usb_device_manager_create_shared_cd_device(priv->manager, filename, &err);
+        if (!rc && err != NULL) {
+            gchar *err_msg = g_strdup_printf(_("shared CD %s, %s"),
+                                             g_path_get_basename(filename), err->message);
+
+            SPICE_DEBUG("Failed to create %s", err_msg);
+            spice_usb_device_widget_add_err_msg(self, err_msg);
+            spice_usb_device_widget_update_status(user_data);
+
+            g_clear_error(&err);
+        }
+    }
+    gtk_widget_destroy(dialog);
+}
+
+static void spice_usb_device_widget_add_empty_cd(SpiceUsbDeviceWidget *self)
+{
+    SpiceUsbDeviceWidgetPrivate *priv = self->priv;
+    GtkWidget *empty_cd, *cd_label;
+
+    empty_cd = gtk_check_button_new_with_label(_("SPICE CD (empty)"));
+    cd_label = gtk_bin_get_child(GTK_BIN(empty_cd));
+    gtk_label_set_ellipsize(GTK_LABEL(cd_label), PANGO_ELLIPSIZE_MIDDLE);
+    g_signal_connect(G_OBJECT(empty_cd), "toggled", G_CALLBACK(empty_cd_clicked_cb), self);
+
+    gtk_widget_set_margin_start(empty_cd, 12);
+    gtk_box_pack_end(GTK_BOX(self), empty_cd, FALSE, FALSE, 0);
+    gtk_widget_show_all(empty_cd);
+
+    priv->empty_cd = empty_cd;
+}
+
 static void spice_usb_device_widget_constructed(GObject *gobject)
 {
     SpiceUsbDeviceWidget *self;
@@ -227,6 +289,8 @@ static void spice_usb_device_widget_constructed(GObject *gobject)
     g_signal_connect(priv->manager, "device-error",
                      G_CALLBACK(device_error_cb), self);
 
+    spice_usb_device_widget_add_empty_cd(self);
+
     devices = spice_usb_device_manager_get_devices(priv->manager);
     if (devices != NULL) {
         int i;
@@ -557,6 +621,15 @@ static void device_added_cb(SpiceUsbDeviceManager *manager,
 
     gtk_widget_set_margin_start(check, 12);
     gtk_box_pack_end(GTK_BOX(self), check, FALSE, FALSE, 0);
+
+    gtk_box_reorder_child(GTK_BOX(self), priv->empty_cd, -1);
+
+    if (spice_usb_device_manager_is_device_shared_cd(priv->manager, device) &&
+        !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check))) {
+            /* checkbox toggl will initiate redirect */
+            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
+    }
+
     spice_usb_device_widget_update_status(self);
     gtk_widget_show_all(check);
 }
commit 2a256ad0b4548a7984b54dd42da5c743f920ecd5
Author: Alexander Nezhinsky <anezhins at redhat.com>
Date:   Wed Dec 11 17:17:41 2019 +0200

    add spice_usb_device_manager shared CD related api functions
    
    The following functions are added:
    spice_usb_device_manager_create_shared_cd_device
    spice_usb_device_manager_is_device_shared_cd
    spice_usb_device_manager_remove_shared_cd_device
    
    Acked-by: Frediano Ziglio <fziglio at redhat.com>

diff --git a/src/map-file b/src/map-file
index 3cb9873..5ae56c3 100644
--- a/src/map-file
+++ b/src/map-file
@@ -180,6 +180,9 @@ spice_usb_device_manager_get_devices_with_filter;
 spice_usb_device_manager_get_type;
 spice_usb_device_manager_is_device_connected;
 spice_usb_device_manager_is_redirecting;
+spice_usb_device_manager_create_shared_cd_device;
+spice_usb_device_manager_remove_shared_cd_device;
+spice_usb_device_manager_is_device_shared_cd;
 spice_usb_device_widget_get_type;
 spice_usb_device_widget_new;
 spice_usbredir_channel_get_type;
diff --git a/src/usb-device-manager.c b/src/usb-device-manager.c
index 1810e18..9b7e538 100644
--- a/src/usb-device-manager.c
+++ b/src/usb-device-manager.c
@@ -32,6 +32,7 @@
 #endif
 
 #include "channel-usbredir-priv.h"
+#include "usb-device-cd.h"
 #endif
 
 #include "spice-session-priv.h"
@@ -1427,6 +1428,85 @@ gchar *spice_usb_device_get_description(SpiceUsbDevice *device, const gchar *for
 #endif
 }
 
+/**
+ * spice_usb_device_manager_create_shared_cd_device:
+ * @manager: a #SpiceUsbDeviceManager
+ * @filename: image or device path
+ * @err: (allow-none): a return location for a #GError, or %NULL.
+ *
+ * Creates a new shared CD device based on a disk image file
+ * or a physical CD device.
+ *
+ * Returns: %TRUE if device created successfully
+ */
+gboolean
+spice_usb_device_manager_create_shared_cd_device(SpiceUsbDeviceManager *manager,
+                                                 gchar *filename,
+                                                 GError **err)
+{
+#ifdef USE_USBREDIR
+    SpiceUsbDeviceManagerPrivate *priv = manager->priv;
+
+    CdEmulationParams cd_params = {
+        .filename = filename,
+        .delete_on_eject = 1,
+    };
+
+    return create_emulated_cd(priv->context, &cd_params, err);
+#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_manager_remove_shared_cd_device:
+ * @manager: a #SpiceUsbDeviceManager
+ * @device: a #SpiceUsbDevice to remove
+ * @err: (allow-none): a return location for a #GError, or %NULL.
+ *
+ * Removes a shared CD device.
+ *
+ * Returns: %TRUE if device removed successfully
+ */
+gboolean
+spice_usb_device_manager_remove_shared_cd_device(SpiceUsbDeviceManager *manager,
+                                                 SpiceUsbDevice *device,
+                                                 GError **err)
+{
+#ifdef USE_USBREDIR
+    spice_usb_backend_device_eject(manager->priv->context, device);
+    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_manager_is_device_shared_cd:
+ * @manager: a #SpiceUsbDeviceManager
+ * @device: a #SpiceUsbDevice to query
+ *
+ * Checks whether a device is shared CD.
+ *
+ * Returns: %TRUE if the device is shared CD
+ */
+gboolean
+spice_usb_device_manager_is_device_shared_cd(SpiceUsbDeviceManager *manager,
+                                             SpiceUsbDevice *device)
+{
+#ifdef USE_USBREDIR
+    gboolean is_cd = (spice_usb_backend_device_get_libdev(device) == NULL);
+
+    return is_cd;
+#else
+    return FALSE;
+#endif
+}
+
 #ifdef USE_USBREDIR
 /*
  * SpiceUsbDevice
diff --git a/src/usb-device-manager.h b/src/usb-device-manager.h
index 1048416..cfa29df 100644
--- a/src/usb-device-manager.h
+++ b/src/usb-device-manager.h
@@ -145,6 +145,18 @@ spice_usb_device_manager_can_redirect_device(SpiceUsbDeviceManager *manager,
 
 gboolean spice_usb_device_manager_is_redirecting(SpiceUsbDeviceManager *manager);
 
+gboolean
+spice_usb_device_manager_create_shared_cd_device(SpiceUsbDeviceManager *manager,
+                                                 gchar *filename,
+                                                 GError **err);
+gboolean
+spice_usb_device_manager_remove_shared_cd_device(SpiceUsbDeviceManager *manager,
+                                                 SpiceUsbDevice *device,
+                                                 GError **err);
+gboolean
+spice_usb_device_manager_is_device_shared_cd(SpiceUsbDeviceManager *manager,
+                                             SpiceUsbDevice *device);
+
 G_END_DECLS
 
 #endif /* __SPICE_USB_DEVICE_MANAGER_H__ */


More information about the Spice-commits mailing list