[Spice-devel] [PATCH spice-gtk 5/5] Teach spicy to use a NBD channel

Marc-André Lureau marcandre.lureau at gmail.com
Fri Nov 15 13:15:11 PST 2013


From: Marc-André Lureau <marcandre.lureau at redhat.com>

---
 gtk/spicy.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 94 insertions(+), 7 deletions(-)

diff --git a/gtk/spicy.c b/gtk/spicy.c
index dff9d44..7f6a169 100644
--- a/gtk/spicy.c
+++ b/gtk/spicy.c
@@ -97,6 +97,7 @@ struct spice_connection {
     SpiceSession     *session;
     SpiceGtkSession  *gtk_session;
     SpiceMainChannel *main;
+    SpiceNbdChannel  *nbd_channel;
     SpiceWindow     *wins[CHANNELID_MAX * MONITORID_MAX];
     SpiceAudio       *audio;
     const char       *mouse_state;
@@ -121,6 +122,8 @@ static void del_window(spice_connection *conn, SpiceWindow *win);
 static gboolean fullscreen = false;
 static gboolean version = false;
 static char *spicy_title = NULL;
+static gchar *nbd_file = NULL;
+
 /* globals */
 static GMainLoop     *mainloop = NULL;
 static int           connections = 0;
@@ -373,6 +376,49 @@ static void menu_cb_connect(GtkAction *action, void *data)
     connection_connect(conn);
 }
 
+static void nbd_set_file_finished(GObject *source_object,
+                                  GAsyncResult *res,
+                                  gpointer user_data)
+{
+    SpiceNbdChannel *nbd = SPICE_NBD_CHANNEL(source_object);
+    GError *error = NULL;
+
+    if (!spice_nbd_channel_set_file_finish(nbd, res, &error)) {
+        g_warning("Failed to set NBD file: %s", error->message);
+        g_clear_error(&error);
+    }
+}
+
+static void update_nbd_export(struct spice_connection *conn, const gchar *path)
+{
+    GFile *file = NULL;
+
+    if (path)
+        file = g_file_new_for_path(path);
+
+    spice_nbd_channel_set_file_async(conn->nbd_channel, file, SPICE_NBD_OPEN_NONE,
+                                     NULL, nbd_set_file_finished, conn);
+}
+
+static void menu_cb_change_nbd(GtkAction *action, void *data)
+{
+    GtkWidget *chooser;
+    SpiceWindow *win = data;
+
+    chooser = gtk_file_chooser_dialog_new(_("Select disk image"),
+                                          GTK_WINDOW(win->toplevel),
+                                          GTK_FILE_CHOOSER_ACTION_OPEN,
+                                          GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                                          GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
+                                          NULL);
+    if (gtk_dialog_run(GTK_DIALOG(chooser)) == GTK_RESPONSE_ACCEPT) {
+        gchar *path = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(chooser));
+        update_nbd_export(win->conn, path);
+        g_free(path);
+    }
+    gtk_widget_destroy(chooser);
+}
+
 static void menu_cb_close(GtkAction *action, void *data)
 {
     SpiceWindow *win = data;
@@ -761,6 +807,10 @@ static const GtkActionEntry entries[] = {
         .label       = N_("_Connect ..."),
         .callback    = G_CALLBACK(menu_cb_connect),
     },{
+        .name        = "ChangeNBD",
+        .label       = N_("_Change NBD image"),
+        .callback    = G_CALLBACK(menu_cb_change_nbd),
+    },{
         .name        = "Close",
         .stock_id    = GTK_STOCK_CLOSE,
         .label       = N_("_Close"),
@@ -878,6 +928,7 @@ static char ui_xml[] =
 "      <menuitem action='Connect'/>\n"
 "      <menu action='FileRecentMenu'/>\n"
 "      <separator/>\n"
+"      <menuitem action='ChangeNBD'/>\n"
 "      <menuitem action='Close'/>\n"
 "    </menu>\n"
 "    <menu action='EditMenu'>\n"
@@ -1322,24 +1373,39 @@ static void display_mark(SpiceChannel *channel, gint mark, SpiceWindow *win)
     }
 }
 
-static void update_auto_usbredir_sensitive(spice_connection *conn)
+static void update_action_sensitive(spice_connection *conn,
+                                    const gchar *action, gboolean sensitive)
 {
-#ifdef USE_USBREDIR
     int i;
     GtkAction *ac;
-    gboolean sensitive;
 
-    sensitive = spice_session_has_channel_type(conn->session,
-                                               SPICE_CHANNEL_USBREDIR);
     for (i = 0; i < SPICE_N_ELEMENTS(conn->wins); i++) {
         if (conn->wins[i] == NULL)
             continue;
-        ac = gtk_action_group_get_action(conn->wins[i]->ag, "auto-usbredir");
+        ac = gtk_action_group_get_action(conn->wins[i]->ag, action);
         gtk_action_set_sensitive(ac, sensitive);
     }
+}
+
+static void update_auto_usbredir_sensitive(spice_connection *conn)
+{
+#ifdef USE_USBREDIR
+    gboolean sensitive;
+
+    sensitive = spice_session_has_channel_type(conn->session, SPICE_CHANNEL_USBREDIR);
+    update_action_sensitive(conn, "auto-usbredir", sensitive);
 #endif
 }
 
+static void update_nbd_sensitive(spice_connection *conn)
+{
+    gboolean sensitive;
+
+    sensitive = spice_session_has_channel_type(conn->session, SPICE_CHANNEL_NBD);
+    update_action_sensitive(conn, "ChangeNBD", sensitive);
+}
+
+
 static SpiceWindow* get_window(spice_connection *conn, int channel_id, int monitor_id)
 {
     g_return_val_if_fail(channel_id < CHANNELID_MAX, NULL);
@@ -1401,6 +1467,7 @@ static void display_monitors(SpiceChannel *display, GParamSpec *pspec,
                                           G_CALLBACK(display_mark), w, 0);
             gtk_widget_show(w->toplevel);
             update_auto_usbredir_sensitive(conn);
+            update_nbd_sensitive(conn);
         }
     }
 
@@ -1475,6 +1542,7 @@ static void port_opened(SpiceChannel *channel, GParamSpec *pspec,
         /* only send a break event and disconnect */
         if (g_strcmp0(name, "org.spice.spicy.break") == 0) {
             spice_port_event(port, SPICE_PORT_EVENT_BREAK);
+            spice_channel_flush_async(channel, NULL, port_flushed_cb, conn);
         }
 
         /* handle the first spicy port and connect it to stdin/out */
@@ -1486,7 +1554,6 @@ static void port_opened(SpiceChannel *channel, GParamSpec *pspec,
         if (port == stdin_port)
             goto end;
 
-        spice_channel_flush_async(channel, NULL, port_flushed_cb, conn);
     } else {
         if (port == stdin_port)
             stdin_port = NULL;
@@ -1565,6 +1632,15 @@ static void channel_new(SpiceSession *s, SpiceChannel *channel, gpointer data)
                          G_CALLBACK(port_data), conn);
         spice_channel_connect(channel);
     }
+
+    if (SPICE_IS_NBD_CHANNEL(channel)) {
+        SpiceNbdChannel *nbd = SPICE_NBD_CHANNEL(channel);
+        update_nbd_sensitive(conn);
+        SPICE_DEBUG("new nbd channel");
+        conn->nbd_channel = nbd;
+        spice_channel_connect(channel);
+        update_nbd_export(conn, nbd_file);
+    }
 }
 
 static void channel_destroy(SpiceSession *s, SpiceChannel *channel, gpointer data)
@@ -1593,6 +1669,10 @@ static void channel_destroy(SpiceSession *s, SpiceChannel *channel, gpointer dat
         update_auto_usbredir_sensitive(conn);
     }
 
+    if (SPICE_IS_NBD_CHANNEL(channel)) {
+        update_nbd_sensitive(conn);
+    }
+
     if (SPICE_IS_PORT_CHANNEL(channel)) {
         if (SPICE_PORT_CHANNEL(channel) == stdin_port)
             stdin_port = NULL;
@@ -1693,6 +1773,12 @@ static GOptionEntry cmd_entries[] = {
         .description      = N_("Set the window title"),
         .arg_description  = N_("<title>"),
     },{
+        .long_name        = "nbd-file",
+        .arg              = G_OPTION_ARG_FILENAME,
+        .arg_data         = &nbd_file,
+        .description      = N_("image file (for NBD channels)"),
+        .arg_description  = N_("<FILE>"),
+    },{
         /* end of list */
     }
 };
@@ -1888,6 +1974,7 @@ int main(int argc, char *argv[])
     g_key_file_free(keyfile);
 
     g_free(spicy_title);
+    g_free(nbd_file);
 
     setup_terminal(true);
     return 0;
-- 
1.8.3.1



More information about the Spice-devel mailing list