[virt-tools-list] [PATCH v2 13/16] spice: hook into port channel to create VTE terminals

Marc-André Lureau marcandre.lureau at redhat.com
Fri Dec 21 13:21:33 UTC 2018


Hi

On Fri, Dec 21, 2018 at 4:03 PM Victor Toso <victortoso at redhat.com> wrote:
>
> Hi,
>
> On Wed, Sep 26, 2018 at 07:26:36PM +0400, marcandre.lureau at redhat.com wrote:
> > From: Marc-André Lureau <marcandre.lureau at redhat.com>
> >
> > QEMU defines a few Spice port channel names in
> > docs/spice-port-fqdn.txt that can be interacted with a terminal.
> >
> > Create VirtViewerDisplayVte display for all known terminal channel,
> > and redirect read/write signals.
> >
> > Note that if VTE support is disabled, or if the VTE console isn't
> > shown, spice-gtk will still process those port channels (discarding
> > the read if VTE is disabled).
> >
> > Signed-off-by: Marc-André Lureau <marcandre.lureau at redhat.com>
> > ---
> >  src/virt-viewer-session-spice.c | 118 +++++++++++++++++++++++++++++++-
> >  1 file changed, 116 insertions(+), 2 deletions(-)
> >
> > diff --git a/src/virt-viewer-session-spice.c b/src/virt-viewer-session-spice.c
> > index cb06af2..8aa2351 100644
> > --- a/src/virt-viewer-session-spice.c
> > +++ b/src/virt-viewer-session-spice.c
> > @@ -34,6 +34,7 @@
> >  #include "virt-viewer-util.h"
> >  #include "virt-viewer-session-spice.h"
> >  #include "virt-viewer-display-spice.h"
> > +#include "virt-viewer-display-vte.h"
> >  #include "virt-viewer-auth.h"
> >
> >  G_DEFINE_TYPE (VirtViewerSessionSpice, virt_viewer_session_spice, VIRT_VIEWER_TYPE_SESSION)
> > @@ -955,20 +956,116 @@ on_new_file_transfer(SpiceMainChannel *channel G_GNUC_UNUSED,
> >                                                task);
> >  }
> >
> > +static void
> > +spice_port_write_finished(GObject *source_object,
> > +                          GAsyncResult *res,
> > +                          gpointer dup)
> > +{
> > +    SpicePortChannel *port = SPICE_PORT_CHANNEL(source_object);
> > +    GError *err = NULL;
> > +
> > +    spice_port_channel_write_finish(port, res, &err);
> > +    if (err) {
> > +        g_warning("Spice port write failed: %s", err->message);
> > +        g_error_free(err);
> > +    }
> > +    g_free(dup);
> > +}
> > +
> > +static void
> > +spice_vte_commit(SpicePortChannel *port, const char *text,
> > +                 guint size, gpointer user_data G_GNUC_UNUSED)
> > +{
> > +    void *dup = g_memdup(text, size);
> > +
> > +    /* note: spice-gtk queues write */
> > +    spice_port_channel_write_async(port, dup, size,
> > +                                   NULL, spice_port_write_finished, dup);
> > +}
> > +
> > +static void
> > +spice_port_data(VirtViewerDisplayVte *vte, gpointer data, int size,
> > +                SpicePortChannel *port G_GNUC_UNUSED)
> > +{
> > +    virt_viewer_display_vte_feed(vte, data, size);
> > +}
> > +
> > +static const char *
> > +port_name_to_vte_name(const char *name)
> > +{
> > +    if (g_str_equal(name, "org.qemu.console.serial.0"))
> > +        return _("Serial");
> > +    else if (g_str_equal(name, "org.qemu.monitor.hmp.0"))
> > +        return _("QEMU human monitor");
> > +    else if (g_str_equal(name, "org.qemu.console.debug.0"))
> > +        return _("QEMU debug console");
> > +
> > +    return NULL;
> > +}
> > +
> > +static void
> > +spice_port_opened(SpiceChannel *channel, GParamSpec *pspec G_GNUC_UNUSED,
> > +                  VirtViewerSessionSpice *self)
> > +{
> > +    SpicePortChannel *port = SPICE_PORT_CHANNEL(channel);
> > +    int id;
> > +    gchar *name = NULL;
> > +    gboolean opened = FALSE;
> > +    const char *vte_name;
> > +    GtkWidget *vte;
> > +
> > +    g_object_get(G_OBJECT(port),
> > +                 "channel-id", &id,
> > +                 "port-name", &name,
> > +                 "port-opened", &opened,
> > +                 NULL);
> > +
> > +    g_return_if_fail(name != NULL);
> > +    g_debug("port#%d %s: %s", id, name, opened ? "opened" : "closed");
>
> better to set vte_name and check it now and g_free(name) here so
> you can remove the goto ..

ok

>
> > +    vte = g_object_get_data(G_OBJECT(port), "virt-viewer-vte");
> > +    if (vte) {
> > +        if (opened)
> > +            goto end;
> > +
>
> No need to unref it?

good catch, added unref.

>
> > +        g_object_set_data(G_OBJECT(port), "virt-viewer-vte", NULL);
> > +        virt_viewer_session_remove_display(VIRT_VIEWER_SESSION(self), VIRT_VIEWER_DISPLAY(vte));
> > +
> > +    } else if (opened) {
> > +        vte_name = port_name_to_vte_name(name);
> > +        if (!vte_name)
> > +            goto end;
> > +
> > +        vte = virt_viewer_display_vte_new(VIRT_VIEWER_SESSION(self), vte_name);
> > +        g_object_set_data(G_OBJECT(port), "virt-viewer-vte", g_object_ref_sink(vte));
> > +        virt_viewer_session_add_display(VIRT_VIEWER_SESSION(self), VIRT_VIEWER_DISPLAY(vte));
> > +        virt_viewer_signal_connect_object(vte, "commit",
> > +                                          G_CALLBACK(spice_vte_commit), port, G_CONNECT_SWAPPED);
> > +        virt_viewer_signal_connect_object(port, "port-data",
> > +                                          G_CALLBACK(spice_port_data), vte, G_CONNECT_SWAPPED);
> > +    }
> > +
> > +end:
> > +    g_free(name);
> > +}
> > +
> >  static void
> >  virt_viewer_session_spice_channel_new(SpiceSession *s,
> >                                        SpiceChannel *channel,
> >                                        VirtViewerSession *session)
> >  {
> >      VirtViewerSessionSpice *self = VIRT_VIEWER_SESSION_SPICE(session);
> > -    int id;
> > +    int id, type;
> >
> >      g_return_if_fail(self != NULL);
> >
> >      virt_viewer_signal_connect_object(channel, "open-fd",
> >                                        G_CALLBACK(virt_viewer_session_spice_channel_open_fd_request), self, 0);
> >
> > -    g_object_get(channel, "channel-id", &id, NULL);
> > +    g_object_get(channel,
> > +                 "channel-id", &id,
> > +                 "channel-type", &type,
> > +                 NULL);
> >
> >      g_debug("New spice channel %p %s %d", channel, g_type_name(G_OBJECT_TYPE(channel)), id);
> >
> > @@ -1017,6 +1114,13 @@ virt_viewer_session_spice_channel_new(SpiceSession *s,
> >              virt_viewer_session_set_has_usbredir(session, TRUE);
> >      }
> >
> > +    /* the port channel object is also sub-classed for webdav... */
> > +    if (SPICE_IS_PORT_CHANNEL(channel) && type == SPICE_CHANNEL_PORT) {
> > +        virt_viewer_signal_connect_object(channel, "notify::port-opened",
> > +                                          G_CALLBACK(spice_port_opened), self, 0);
> > +        spice_channel_connect(channel);
> > +    }
> > +
> >      self->priv->channel_count++;
> >  }
> >
> > @@ -1130,6 +1234,16 @@ virt_viewer_session_spice_channel_destroy(G_GNUC_UNUSED SpiceSession *s,
> >          g_object_set_data(G_OBJECT(channel), "virt-viewer-displays", NULL);
> >      }
> >
> > +    if (SPICE_IS_PORT_CHANNEL(channel)) {
> > +        VirtViewerDisplayVte *vte = g_object_get_data(G_OBJECT(channel), "virt-viewer-vte");
> > +        g_debug("zap port channel (#%d)", id);
> > +        if (vte) {
> > +            g_object_set_data(G_OBJECT(channel), "virt-viewer-vte", NULL);
> > +            virt_viewer_session_remove_display(VIRT_VIEWER_SESSION(self), VIRT_VIEWER_DISPLAY(vte));
> > +        }
> > +
> > +    }
> > +
> >      if (SPICE_IS_PLAYBACK_CHANNEL(channel) && self->priv->audio) {
> >          g_debug("zap audio channel");
> >          self->priv->audio = NULL;
> > --
> > 2.19.0.271.gfe8321ec05
>
> Cheers,
> Victor
> >




More information about the virt-tools-list mailing list