[Spice-commits] 4 commits - data/spice-protocol.vapi gtk/controller gtk/spice-channel.c gtk/spice-session.c spice-protocol
Marc-André Lureau
elmarco at kemper.freedesktop.org
Wed Feb 29 08:51:11 PST 2012
data/spice-protocol.vapi | 95 ++++++++++++
gtk/controller/Makefile.am | 15 +
gtk/controller/custom.vapi | 9 +
gtk/controller/dump.c | 117 +++++++++++++++
gtk/controller/foreign-menu.vala | 207 +++++++++++++++++++++++++++
gtk/controller/menu.vala | 6
gtk/controller/namedpipelistener.c | 3
gtk/controller/spice-controller-listener.c | 14 +
gtk/controller/spice-foreign-menu-listener.c | 159 ++++++++++++++++++++
gtk/controller/spice-foreign-menu-listener.h | 47 ++++++
gtk/controller/test.c | 21 ++
gtk/spice-channel.c | 8 -
gtk/spice-session.c | 10 +
spice-protocol | 2
14 files changed, 694 insertions(+), 19 deletions(-)
New commits:
commit 9473c2607941b1e5032b01f1cb580fdf935e5729
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date: Fri Feb 24 10:17:12 2012 +0100
Add a spice-controller-dump testing tool
By default, start a controller listener.
If ran with --menu, start a foreign-menu listener.
diff --git a/gtk/controller/Makefile.am b/gtk/controller/Makefile.am
index 20f1a48..916309e 100644
--- a/gtk/controller/Makefile.am
+++ b/gtk/controller/Makefile.am
@@ -20,7 +20,7 @@ AM_VALAFLAGS = \
$(NULL)
lib_LTLIBRARIES = libspice-controller.la
-noinst_PROGRAMS = test-controller
+noinst_PROGRAMS = test-controller spice-controller-dump
BUILT_SOURCES = controller.vala.stamp
@@ -60,6 +60,9 @@ libspice_controllerinclude_HEADERS = \
test_controller_SOURCES = test.c
test_controller_LDADD = libspice-controller.la
+spice_controller_dump_SOURCES = dump.c
+spice_controller_dump_LDADD = libspice-controller.la
+
controller.vala.stamp: $(libspice_controller_la_VALASOURCES) custom.vapi
@if test -z "$(VALAC)"; then \
echo "" ; \
diff --git a/gtk/controller/dump.c b/gtk/controller/dump.c
new file mode 100644
index 0000000..6541dec
--- /dev/null
+++ b/gtk/controller/dump.c
@@ -0,0 +1,117 @@
+/* Copyright (C) 2011 Red Hat, Inc. */
+
+/* This library is free software; you can redistribute it and/or */
+/* modify it under the terms of the GNU Lesser General Public */
+/* License as published by the Free Software Foundation; either */
+/* version 2.1 of the License, or (at your option) any later version. */
+
+/* This library is distributed in the hope that it will be useful, */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
+/* Lesser General Public License for more details. */
+
+/* You should have received a copy of the GNU Lesser General Public */
+/* License along with this library; if not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdint.h>
+
+#ifdef WIN32
+#include <windows.h>
+#else
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#endif
+
+#include "spice-controller.h"
+
+SpiceCtrlController *ctrl = NULL;
+SpiceCtrlForeignMenu *menu = NULL;
+GMainLoop *loop = NULL;
+
+void signaled (GObject *gobject, const gchar *signal_name)
+{
+ g_message ("signaled: %s", signal_name);
+}
+
+void notified (GObject *gobject, GParamSpec *pspec,
+ gpointer user_data)
+{
+ GValue value = { 0, };
+ GValue strvalue = { 0, };
+
+ g_return_if_fail (gobject != NULL);
+ g_return_if_fail (pspec != NULL);
+
+ g_value_init (&value, pspec->value_type);
+ g_value_init (&strvalue, G_TYPE_STRING);
+ g_object_get_property (gobject, pspec->name, &value);
+
+ if (pspec->value_type == G_TYPE_STRV) {
+ gchar** p = (gchar **)g_value_get_boxed (&value);
+ g_message ("notify::%s == ", pspec->name);
+ while (*p)
+ g_message ("%s", *p++);
+ } else if (G_TYPE_IS_OBJECT(pspec->value_type)) {
+ GObject *o = g_value_get_object (&value);
+ g_message ("notify::%s == %s", pspec->name, o ? G_OBJECT_TYPE_NAME (o) : "null");
+ } else {
+ g_value_transform (&value, &strvalue);
+ g_message ("notify::%s = %s", pspec->name, g_value_get_string (&strvalue));
+ }
+
+ g_value_unset (&value);
+ g_value_unset (&strvalue);
+}
+
+void connect_signals (gpointer obj)
+{
+ guint i, n_ids = 0;
+ guint *ids = NULL;
+ GType type = G_OBJECT_TYPE (obj);
+
+ ids = g_signal_list_ids (type, &n_ids);
+ for (i = 0; i < n_ids; i++) {
+ const gchar *name = g_signal_name (ids[i]);
+ g_signal_connect (obj, name, G_CALLBACK (signaled), (gpointer)name);
+ }
+}
+
+int main (int argc, char *argv[])
+{
+ g_type_init ();
+ loop = g_main_loop_new (NULL, FALSE);
+
+ if (argc > 1 && g_str_equal(argv[1], "--menu")) {
+ menu = spice_ctrl_foreign_menu_new ();
+ g_signal_connect (menu, "notify", G_CALLBACK (notified), NULL);
+ connect_signals (menu);
+
+ spice_ctrl_foreign_menu_listen (menu, NULL, NULL, NULL);
+ } else {
+ ctrl = spice_ctrl_controller_new ();
+ g_signal_connect (ctrl, "notify", G_CALLBACK (notified), NULL);
+ connect_signals (ctrl);
+
+ spice_ctrl_controller_listen (ctrl, NULL, NULL, NULL);
+ }
+
+ g_main_loop_run (loop);
+
+ if (ctrl != NULL)
+ g_object_unref (ctrl);
+ if (menu != NULL)
+ g_object_unref (menu);
+
+ return 0;
+}
+
diff --git a/gtk/controller/test.c b/gtk/controller/test.c
index e43d299..3f3eb55 100644
--- a/gtk/controller/test.c
+++ b/gtk/controller/test.c
@@ -174,9 +174,9 @@ void notified (GObject *gobject, GParamSpec *pspec,
g_message ("notify::%s == ", pspec->name);
while (*p)
g_message ("%s", *p++);
- } else if (pspec->value_type == G_TYPE_OBJECT) {
+ } else if (G_TYPE_IS_OBJECT(pspec->value_type)) {
GObject *o = g_value_get_object (&value);
- g_message ("notify::%s == %s", pspec->name, G_OBJECT_TYPE_NAME (o));
+ g_message ("notify::%s == %s", pspec->name, o ? G_OBJECT_TYPE_NAME (o) : "null");
} else {
g_value_transform (&value, &strvalue);
g_message ("notify::%s = %s", pspec->name, g_value_get_string (&strvalue));
@@ -186,6 +186,19 @@ void notified (GObject *gobject, GParamSpec *pspec,
g_value_unset (&strvalue);
}
+void connect_signals (gpointer obj)
+{
+ guint i, n_ids = 0;
+ guint *ids = NULL;
+ GType type = G_OBJECT_TYPE (obj);
+
+ ids = g_signal_list_ids (type, &n_ids);
+ for (i = 0; i < n_ids; i++) {
+ const gchar *name = g_signal_name (ids[i]);
+ g_signal_connect (obj, name, G_CALLBACK (signaled), (gpointer)name);
+ }
+}
+
int main (int argc, char *argv[])
{
int spicec_pid = (argc > 1 ? atoi (argv[1]) : 0);
@@ -199,9 +212,7 @@ int main (int argc, char *argv[])
ctrl = spice_ctrl_controller_new ();
loop = g_main_loop_new (NULL, FALSE);
g_signal_connect (ctrl, "notify", G_CALLBACK (notified), NULL);
- g_signal_connect (ctrl, "show", G_CALLBACK (signaled), "show");
- g_signal_connect (ctrl, "hide", G_CALLBACK (signaled), "hide");
- g_signal_connect (ctrl, "do_connect", G_CALLBACK (signaled), "do_connect");
+ connect_signals (ctrl);
#ifdef WIN32
snprintf (pipe_name, PIPE_NAME_MAX_LEN, PIPE_NAME, spicec_pid);
commit d748bbc86ddfe0fcde475d63cdab0e2d80d2a05b
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date: Mon Feb 20 20:27:29 2012 +0100
Add controller foreign menu support
diff --git a/data/spice-protocol.vapi b/data/spice-protocol.vapi
index 4cb1a2f..6626176 100644
--- a/data/spice-protocol.vapi
+++ b/data/spice-protocol.vapi
@@ -34,7 +34,7 @@ namespace SpiceProtocol {
[CCode (cprefix = "CONTROLLER_")]
public enum MsgId {
- //extrenal app -> spice client
+ //external app -> spice client
HOST,
PORT,
SPORT,
@@ -62,7 +62,7 @@ namespace SpiceProtocol {
ENABLE_SMARTCARD,
- //spice client -> extrenal app
+ //spice client -> external app
MENU_ITEM_CLICK,
}
@@ -107,4 +107,95 @@ namespace SpiceProtocol {
GRAYED,
}
}
+
+ [CCode (cprefix = "FrgMenu", cheader_filename = "spice/foreign_menu_prot.h")]
+ namespace ForeignMenu {
+ [CCode (cname = "FOREIGN_MENU_MAGIC")]
+ public const uint32 MAGIC;
+ [CCode (cname = "FOREIGN_MENU_VERSION")]
+ public const int VERSION;
+
+ [Compact]
+ public struct InitHeader {
+ uint32 magic;
+ uint32 version;
+ uint32 size;
+ }
+
+ [Compact]
+ [CCode (has_destroy_function = false)]
+ public struct Init {
+ InitHeader base;
+ uint64 credentials;
+ string title; // utf8
+ }
+
+ [Compact]
+ public struct Msg {
+ uint32 id;
+ uint32 size;
+ }
+
+ [CCode (cprefix = "FOREIGN_MENU_", cname = "int")]
+ public enum MsgId {
+ //external app -> spice client
+ SET_TITLE,
+ ADD_ITEM,
+ MODIFY_ITEM,
+ REMOVE_ITEM,
+ CLEAR,
+
+ //spice client -> external app
+ ITEM_EVENT,
+ APP_ACTIVATED,
+ APP_DEACTIVATED,
+ }
+
+ [Compact]
+ [CCode (cname = "FrgMenuSetTitle")]
+ public struct SetTitle {
+ Msg base;
+ string string; // utf8
+ }
+
+ [CCode (cprefix = "FOREIGN_MENU_ITEM_TYPE_", cname = "unsigned int", has_type_id = false)]
+ [Flags]
+ public enum MenuFlags {
+ CHECKED,
+ DIM,
+ SEPARATOR
+ }
+
+ [Compact]
+ [CCode (cname = "FrgMenuAddItem")]
+ public struct AddItem {
+ Msg base;
+ uint32 id;
+ uint32 type;
+ uint32 position;
+ string string; // utf8
+ }
+
+ [Compact]
+ [CCode (cname = "FrgMenuRmItem")]
+ public struct RmItem {
+ Msg base;
+ uint32 id;
+ }
+
+ [CCode (cprefix = "FOREIGN_MENU_EVENT_", cname = "int")]
+ public enum EventType {
+ CLICK,
+ CHECKED,
+ UNCHECKED,
+ }
+
+ [Compact]
+ [CCode (cname = "FrgMenuEvent")]
+ public struct Event {
+ Msg base;
+ uint32 id;
+ uint32 action;
+ }
+ }
}
diff --git a/gtk/controller/Makefile.am b/gtk/controller/Makefile.am
index 522e014..20f1a48 100644
--- a/gtk/controller/Makefile.am
+++ b/gtk/controller/Makefile.am
@@ -1,6 +1,11 @@
NULL =
-AM_CPPFLAGS = $(GIO_CFLAGS) $(PROTOCOL_CFLAGS)
+AM_CPPFLAGS = \
+ -DG_LOG_DOMAIN=\"GSpiceController\" \
+ $(GIO_CFLAGS) \
+ $(PROTOCOL_CFLAGS) \
+ $(NULL)
+
# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
AM_LDFLAGS = \
-no-undefined \
@@ -22,11 +27,14 @@ BUILT_SOURCES = controller.vala.stamp
libspice_controller_la_VALASOURCES = \
menu.vala \
controller.vala \
+ foreign-menu.vala \
$(NULL)
libspice_controller_la_SOURCES = \
custom.h \
spice-controller-listener.c \
spice-controller-listener.h \
+ spice-foreign-menu-listener.c \
+ spice-foreign-menu-listener.h \
$(libspice_controller_la_VALASOURCES:.vala=.c) \
$(NULL)
diff --git a/gtk/controller/custom.vapi b/gtk/controller/custom.vapi
index 7a94b82..a12fdec 100644
--- a/gtk/controller/custom.vapi
+++ b/gtk/controller/custom.vapi
@@ -16,4 +16,13 @@ namespace Spice {
[CCode (cname = "spice_controller_listener_accept_async", cheader_filename = "spice-controller-listener.h")]
public async unowned GLib.IOStream accept_async (GLib.Cancellable? cancellable = null, out GLib.Object? source_object = null) throws GLib.Error;
}
+
+ [CCode (cname = "GObject", ref_function = "g_object_ref", unref_function = "g_object_unref", free_function = "")]
+ class ForeignMenuListener {
+ [CCode (cname = "spice_foreign_menu_listener_new", cheader_filename = "spice-foreign-menu-listener.h")]
+ public static ForeignMenuListener new_listener (string addr) throws GLib.Error;
+
+ [CCode (cname = "spice_foreign_menu_listener_accept_async", cheader_filename = "spice-foreign-menu-listener.h")]
+ public async unowned GLib.IOStream accept_async (GLib.Cancellable? cancellable = null, out GLib.Object? source_object = null) throws GLib.Error;
+ }
}
diff --git a/gtk/controller/foreign-menu.vala b/gtk/controller/foreign-menu.vala
new file mode 100644
index 0000000..677e2ad
--- /dev/null
+++ b/gtk/controller/foreign-menu.vala
@@ -0,0 +1,207 @@
+// Copyright (C) 2012 Red Hat, Inc.
+
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, see <http://www.gnu.org/licenses/>.
+
+using Custom;
+
+namespace SpiceCtrl {
+
+public class ForeignMenu: Object {
+
+ public Menu menu { get; private set; }
+ public string title { get; private set; }
+
+ private int nclients;
+ private List<IOStream> clients;
+
+ public ForeignMenu() {
+ menu = new Menu ();
+ }
+
+ public void menu_item_click_msg (int32 item_id) {
+ debug ("clicked id: %d".printf (item_id));
+
+ var msg = SpiceProtocol.ForeignMenu.Event ();
+ msg.base.size = (uint32)sizeof (SpiceProtocol.ForeignMenu.Event);
+ msg.base.id = SpiceProtocol.ForeignMenu.MsgId.ITEM_EVENT;
+ msg.id = item_id;
+ msg.action = SpiceProtocol.ForeignMenu.EventType.CLICK;
+
+ unowned uint8[] p = ((uint8[])(&msg))[0:msg.base.size];
+ send_msg (p);
+ }
+
+ public void menu_item_checked_msg (int32 item_id, bool checked = true) {
+ debug ("%schecked id: %d".printf (checked ? "" : "un", item_id));
+
+ var msg = SpiceProtocol.ForeignMenu.Event ();
+ msg.base.size = (uint32)sizeof (SpiceProtocol.ForeignMenu.Event);
+ msg.base.id = SpiceProtocol.ForeignMenu.MsgId.ITEM_EVENT;
+ msg.id = item_id;
+ msg.action = checked ?
+ SpiceProtocol.ForeignMenu.EventType.CHECKED :
+ SpiceProtocol.ForeignMenu.EventType.UNCHECKED;
+
+ unowned uint8[] p = ((uint8[])(&msg))[0:msg.base.size];
+ send_msg (p);
+ }
+
+ public void app_activated_msg (bool activated = true) {
+ var msg = SpiceProtocol.ForeignMenu.Msg ();
+ msg.size = (uint32)sizeof (SpiceProtocol.ForeignMenu.Event);
+ msg.id = activated ?
+ SpiceProtocol.ForeignMenu.MsgId.APP_ACTIVATED :
+ SpiceProtocol.ForeignMenu.MsgId.APP_DEACTIVATED;
+
+ unowned uint8[] p = ((uint8[])(&msg))[0:msg.size];
+ send_msg (p);
+ }
+
+ public async bool send_msg (uint8[] p) throws GLib.Error {
+ // vala FIXME: pass Controller.Msg instead
+ // vala doesn't keep reference on the struct in async methods
+ // it copies only base, which is not enough to transmit the whole
+ // message.
+ try {
+ foreach (var c in clients)
+ yield c.output_stream.write_async (p);
+ } catch (GLib.Error e) {
+ warning (e.message);
+ }
+
+ return true;
+ }
+
+ SpiceProtocol.Controller.MenuFlags get_menu_flags (uint32 type) {
+ SpiceProtocol.Controller.MenuFlags flags = 0;
+
+ if ((SpiceProtocol.ForeignMenu.MenuFlags.CHECKED & type) != 0)
+ flags |= SpiceProtocol.Controller.MenuFlags.CHECKED;
+ if ((SpiceProtocol.ForeignMenu.MenuFlags.DIM & type) != 0)
+ flags |= SpiceProtocol.Controller.MenuFlags.GRAYED;
+
+ return flags;
+ }
+
+ private bool handle_message (SpiceProtocol.ForeignMenu.Msg* msg) {
+ switch (msg.id) {
+ case SpiceProtocol.ForeignMenu.MsgId.SET_TITLE:
+ var t = (SpiceProtocol.ForeignMenu.SetTitle*)(msg);
+ title = t.string;
+ break;
+ case SpiceProtocol.ForeignMenu.MsgId.ADD_ITEM:
+ var i = (SpiceProtocol.ForeignMenu.AddItem*)(msg);
+ debug ("add id:%u type:%u position:%u title:%s", i.id, i.type, i.position, i.string);
+ menu.items.append (new MenuItem ((int)i.id, i.string, get_menu_flags (i.type)));
+ notify_property ("menu");
+ break;
+ case SpiceProtocol.ForeignMenu.MsgId.MODIFY_ITEM:
+ debug ("deprecated: modify item");
+ break;
+ case SpiceProtocol.ForeignMenu.MsgId.REMOVE_ITEM:
+ var i = (SpiceProtocol.ForeignMenu.RmItem*)(msg);
+ debug ("not implemented: remove id:%u".printf (i.id));
+ break;
+ case SpiceProtocol.ForeignMenu.MsgId.CLEAR:
+ menu = new Menu ();
+ break;
+ default:
+ warn_if_reached ();
+ return false;
+ }
+ return true;
+ }
+
+ private async void handle_client (IOStream c) throws GLib.Error {
+ var header = SpiceProtocol.ForeignMenu.InitHeader ();
+ unowned uint8[] p = null;
+
+ debug ("new socket client, reading init header");
+
+ p = ((uint8[])(&header))[0:sizeof(SpiceProtocol.ForeignMenu.InitHeader)]; // FIXME vala
+ var read = yield c.input_stream.read_async (p);
+ if (warn_if (read != sizeof (SpiceProtocol.ForeignMenu.InitHeader)))
+ return;
+ if (warn_if (header.magic != SpiceProtocol.ForeignMenu.MAGIC))
+ return;
+ if (warn_if (header.version != SpiceProtocol.ForeignMenu.VERSION))
+ return;
+ if (warn_if (header.size < sizeof (SpiceProtocol.ForeignMenu.Init)))
+ return;
+
+ uint64 credentials = 0;
+ p = ((uint8[])(&credentials))[0:sizeof(uint64)];
+ read = yield c.input_stream.read_async (p);
+ if (warn_if (read != sizeof(uint64)))
+ return;
+ if (warn_if (credentials != 0))
+ return;
+
+ var title_size = header.size - sizeof(SpiceProtocol.ForeignMenu.Init);
+ var title = new uint8[title_size + 1];
+ read = yield c.input_stream.read_async (title[0:title_size]);
+ this.title = (string)title;
+
+ var t = new uint8[sizeof(SpiceProtocol.ForeignMenu.Msg)];
+ for (;;) {
+ read = yield c.input_stream.read_async (t[0:sizeof(SpiceProtocol.ForeignMenu.Msg)]);
+ if (read == 0)
+ break;
+
+ if (warn_if (read != sizeof (SpiceProtocol.ForeignMenu.Msg))) {
+ warning ("read only: " + read.to_string ());
+ break;
+ }
+
+ var msg = (SpiceProtocol.ForeignMenu.Msg*)t;
+ if (warn_if (msg.size < sizeof (SpiceProtocol.ForeignMenu.Msg)))
+ break;
+
+ if (msg.size > sizeof (SpiceProtocol.ForeignMenu.Msg)) {
+ t.resize ((int)msg.size);
+ msg = (SpiceProtocol.ForeignMenu.Msg*)t;
+ read = yield c.input_stream.read_async (t[sizeof(SpiceProtocol.ForeignMenu.Msg):msg.size]);
+ if (read == 0)
+ break;
+ if (warn_if (read != msg.size - sizeof(SpiceProtocol.ForeignMenu.Msg)))
+ break;
+ }
+
+ handle_message (msg);
+ }
+
+ }
+
+ public async void listen (string? addr = null) throws GLib.Error, SpiceCtrl.Error
+ {
+ var listener = Spice.ForeignMenuListener.new_listener (addr);
+
+ for (;;) {
+ var c = yield listener.accept_async ();
+ nclients += 1;
+ clients.append (c);
+ try {
+ yield handle_client (c);
+ } catch (GLib.Error e) {
+ warning (e.message);
+ }
+ c.close ();
+ clients.remove (c);
+ nclients -= 1;
+ }
+ }
+
+}
+
+} // SpiceCtrl
diff --git a/gtk/controller/menu.vala b/gtk/controller/menu.vala
index 7f2f42a..7e8fc16 100644
--- a/gtk/controller/menu.vala
+++ b/gtk/controller/menu.vala
@@ -28,6 +28,12 @@ public class MenuItem: Object {
public string accel;
public SpiceProtocol.Controller.MenuFlags flags;
+ public MenuItem (int id, string text, SpiceProtocol.Controller.MenuFlags flags) {
+ this.id = id;
+ this.text = text;
+ this.flags = flags;
+ }
+
public MenuItem.from_string (string str) throws SpiceCtrl.Error {
var params = str.split (SpiceProtocol.Controller.MENU_PARAM_DELIMITER);
if (warn_if (params.length != 5))
diff --git a/gtk/controller/spice-foreign-menu-listener.c b/gtk/controller/spice-foreign-menu-listener.c
new file mode 100644
index 0000000..8322a13
--- /dev/null
+++ b/gtk/controller/spice-foreign-menu-listener.c
@@ -0,0 +1,159 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ Copyright (C) 2012 Red Hat, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <glib.h>
+#include <glib/gstdio.h>
+
+#include "spice-foreign-menu-listener.h"
+
+#ifdef G_OS_WIN32
+#include <windows.h>
+#include "namedpipe.h"
+#include "namedpipelistener.h"
+#endif
+
+#ifdef G_OS_UNIX
+#include <gio/gunixsocketaddress.h>
+#endif
+
+/**
+ * SpiceForeignMenuListenerError:
+ * @SPICE_FOREIGN_MENU_LISTENER_ERROR_VALUE: invalid value.
+ *
+ * Possible errors of foreign menu listener related functions.
+ **/
+
+/**
+ * SPICE_FOREIGN_MENU_LISTENER_ERROR:
+ *
+ * The error domain of the foreign menu listener subsystem.
+ **/
+GQuark
+spice_foreign_menu_listener_error_quark (void)
+{
+ return g_quark_from_static_string ("spice-foreign-menu-listener-error");
+}
+
+GObject*
+spice_foreign_menu_listener_new (const gchar *address, GError **error)
+{
+ GObject *listener = NULL;
+ gchar *addr = NULL;
+
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ addr = g_strdup (address);
+
+#ifdef G_OS_WIN32
+ if (addr == NULL)
+ addr = g_strdup (g_getenv ("SPICE_FOREIGN_MENU_NAMEDPIPE"));
+ if (addr == NULL)
+ addr = g_strdup_printf ("\\\\.\\pipe\\SpiceForeignMenu-%" G_GUINT64_FORMAT, (guint64)GetCurrentProcessId ());
+#else
+ if (addr == NULL)
+ addr = g_strdup (g_getenv ("SPICE_FOREIGN_MENU_SOCKET"));
+ if (addr == NULL)
+ addr = g_strdup_printf ("/tmp/SpiceForeignMenu-%" G_GUINT64_FORMAT ".uds", (guint64)getpid ());
+#endif
+ if (addr == NULL) {
+ g_set_error (error,
+ SPICE_FOREIGN_MENU_LISTENER_ERROR,
+ SPICE_FOREIGN_MENU_LISTENER_ERROR_VALUE,
+#ifdef G_OS_WIN32
+ "Missing namedpipe address"
+#else
+ "Missing socket address"
+#endif
+ );
+ goto end;
+ }
+
+ g_unlink (addr);
+
+#ifdef G_OS_WIN32
+ {
+ SpiceNamedPipe *np;
+
+ listener = G_OBJECT (spice_named_pipe_listener_new ());
+
+ np = spice_named_pipe_new (addr, error);
+ if (!np) {
+ g_object_unref (listener);
+ listener = NULL;
+ goto end;
+ }
+
+ spice_named_pipe_listener_add_named_pipe (SPICE_NAMED_PIPE_LISTENER (listener), np);
+ }
+#else
+ {
+ listener = G_OBJECT (g_socket_listener_new ());
+
+ if (!g_socket_listener_add_address (G_SOCKET_LISTENER (listener),
+ G_SOCKET_ADDRESS (g_unix_socket_address_new (addr)),
+ G_SOCKET_TYPE_STREAM,
+ G_SOCKET_PROTOCOL_DEFAULT,
+ NULL,
+ NULL,
+ error))
+ g_warning ("failed to add address");
+ }
+#endif
+
+end:
+ g_free (addr);
+ return listener;
+}
+
+void
+spice_foreign_menu_listener_accept_async (GObject *listener,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_return_if_fail(G_IS_OBJECT(listener));
+
+#ifdef G_OS_WIN32
+ spice_named_pipe_listener_accept_async (SPICE_NAMED_PIPE_LISTENER (listener), cancellable, callback, user_data);
+#else
+ g_socket_listener_accept_async (G_SOCKET_LISTENER (listener), cancellable, callback, user_data);
+#endif
+}
+
+GIOStream*
+spice_foreign_menu_listener_accept_finish (GObject *listener,
+ GAsyncResult *result,
+ GObject **source_object,
+ GError **error)
+{
+ g_return_val_if_fail(G_IS_OBJECT(listener), NULL);
+
+#ifdef G_OS_WIN32
+ SpiceNamedPipeConnection *np;
+ np = spice_named_pipe_listener_accept_finish (SPICE_NAMED_PIPE_LISTENER (listener), result, source_object, error);
+ if (np)
+ return G_IO_STREAM (np);
+#else
+ GSocketConnection *socket;
+ socket = g_socket_listener_accept_finish (G_SOCKET_LISTENER (listener), result, source_object, error);
+ if (socket)
+ return G_IO_STREAM (socket);
+#endif
+
+ return NULL;
+}
diff --git a/gtk/controller/spice-foreign-menu-listener.h b/gtk/controller/spice-foreign-menu-listener.h
new file mode 100644
index 0000000..1071528
--- /dev/null
+++ b/gtk/controller/spice-foreign-menu-listener.h
@@ -0,0 +1,47 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ Copyright (C) 2012 Red Hat, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef __SPICE_FOREIGN_MENU_LISTENER_H__
+#define __SPICE_FOREIGN_MENU_LISTENER_H__
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define SPICE_FOREIGN_MENU_LISTENER_ERROR spice_foreign_menu_listener_error_quark ()
+GQuark spice_foreign_menu_listener_error_quark (void);
+
+typedef enum
+{
+ SPICE_FOREIGN_MENU_LISTENER_ERROR_VALUE /* incorrect value */
+} SpiceForeignMenuListenerError;
+
+
+GObject* spice_foreign_menu_listener_new (const gchar *address, GError **error);
+
+void spice_foreign_menu_listener_accept_async (GObject *listener,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GIOStream* spice_foreign_menu_listener_accept_finish (GObject *listener,
+ GAsyncResult *result,
+ GObject **source_object,
+ GError **error);
+G_END_DECLS
+
+#endif /* __SPICE_FOREIGN_MENU_LISTENER_H__ */
diff --git a/spice-protocol b/spice-protocol
index cda8862..d5edafd 160000
--- a/spice-protocol
+++ b/spice-protocol
@@ -1 +1 @@
-Subproject commit cda88623d0754aeeda005ddc048dd113d279845b
+Subproject commit d5edafd28ab762b1b5f663aec449d3e3743f1184
commit c10b36855ccf2abeb52c7c2be5b64c16ca54d137
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date: Wed Feb 29 14:55:32 2012 +0100
Fix a few warnings on windows build
diff --git a/gtk/controller/namedpipelistener.c b/gtk/controller/namedpipelistener.c
index e8e870d..28b2a4d 100644
--- a/gtk/controller/namedpipelistener.c
+++ b/gtk/controller/namedpipelistener.c
@@ -39,7 +39,7 @@ spice_named_pipe_listener_dispose (GObject *object)
SpiceNamedPipeListener *listener = SPICE_NAMED_PIPE_LISTENER (object);
SpiceNamedPipe *p;
- while (p = g_queue_pop_head (&listener->priv->namedpipes))
+ while ((p = g_queue_pop_head (&listener->priv->namedpipes)) != NULL)
g_object_unref (p);
g_return_if_fail (g_queue_get_length (&listener->priv->namedpipes) == 0);
@@ -239,7 +239,6 @@ spice_named_pipe_listener_accept_finish (SpiceNamedPipeListener *listener,
GSimpleAsyncResult *simple;
ConnectData *c;
SpiceNamedPipeConnection *connection;
- gboolean success;
g_return_val_if_fail (SPICE_IS_NAMED_PIPE_LISTENER (listener), NULL);
g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), NULL);
diff --git a/gtk/controller/spice-controller-listener.c b/gtk/controller/spice-controller-listener.c
index 076f74e..da1121e 100644
--- a/gtk/controller/spice-controller-listener.c
+++ b/gtk/controller/spice-controller-listener.c
@@ -63,7 +63,7 @@ spice_controller_listener_new (const gchar *address, GError **error)
if (addr == NULL)
addr = g_strdup (g_getenv ("SPICE_XPI_NAMEDPIPE"));
if (addr == NULL)
- addr = g_strdup_printf ("\\\\.\\pipe\\SpiceController-%lu", GetCurrentProcessId ());
+ addr = g_strdup_printf ("\\\\.\\pipe\\SpiceController-%" G_GUINT64_FORMAT, (guint64)GetCurrentProcessId ());
#else
if (addr == NULL)
addr = g_strdup (g_getenv ("SPICE_XPI_SOCKET"));
@@ -142,8 +142,16 @@ spice_controller_listener_accept_finish (GObject *listener,
g_return_val_if_fail(G_IS_OBJECT(listener), NULL);
#ifdef G_OS_WIN32
- spice_named_pipe_listener_accept_finish (SPICE_NAMED_PIPE_LISTENER (listener), result, source_object, error);
+ SpiceNamedPipeConnection *np;
+ np = spice_named_pipe_listener_accept_finish (SPICE_NAMED_PIPE_LISTENER (listener), result, source_object, error);
+ if (np)
+ return G_IO_STREAM (np);
#else
- g_socket_listener_accept_finish (G_SOCKET_LISTENER (listener), result, source_object, error);
+ GSocketConnection *socket;
+ socket = g_socket_listener_accept_finish (G_SOCKET_LISTENER (listener), result, source_object, error);
+ if (socket)
+ return G_IO_STREAM (socket);
#endif
+
+ return NULL;
}
commit 161c0fc6b0d031687491d4e498e9dcfd2ac089d3
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date: Wed Feb 29 14:01:45 2012 +0100
Allow open_fd() to be called with -1
In this case, a valid fd will be requested via the
SpiceChannel::open-fd signal.
diff --git a/gtk/spice-channel.c b/gtk/spice-channel.c
index 972a3bb..c1c145a 100644
--- a/gtk/spice-channel.c
+++ b/gtk/spice-channel.c
@@ -2302,10 +2302,14 @@ gboolean spice_channel_connect(SpiceChannel *channel)
/**
* spice_channel_open_fd:
* @channel:
- * @fd: a file descriptor (socket)
+ * @fd: a file descriptor (socket) or -1.
+ * request mechanism
*
* Connect the channel using @fd socket.
*
+ * If @fd is -1, a valid fd will be requested later via the
+ * SpiceChannel::open-fd signal.
+ *
* Returns: %TRUE on success.
**/
gboolean spice_channel_open_fd(SpiceChannel *channel, int fd)
@@ -2313,7 +2317,7 @@ gboolean spice_channel_open_fd(SpiceChannel *channel, int fd)
SpiceChannelPrivate *c = SPICE_CHANNEL_GET_PRIVATE(channel);
g_return_val_if_fail(c != NULL, FALSE);
- g_return_val_if_fail(fd >= 0, FALSE);
+ g_return_val_if_fail(fd >= -1, FALSE);
c->fd = fd;
diff --git a/gtk/spice-session.c b/gtk/spice-session.c
index c328f66..991fb60 100644
--- a/gtk/spice-session.c
+++ b/gtk/spice-session.c
@@ -1042,12 +1042,15 @@ gboolean spice_session_connect(SpiceSession *session)
/**
* spice_session_open_fd:
* @session:
- * @fd: a file descriptor
+ * @fd: a file descriptor (socket) or -1
*
* Open the session using the provided @fd socket file
* descriptor. This is useful if you create the fd yourself, for
* example to setup a SSH tunnel.
*
+ * If @fd is -1, a valid fd will be requested later via the
+ * SpiceChannel::open-fd signal.
+ *
* Returns:
**/
gboolean spice_session_open_fd(SpiceSession *session, int fd)
@@ -1055,14 +1058,17 @@ gboolean spice_session_open_fd(SpiceSession *session, int fd)
SpiceSessionPrivate *s = SPICE_SESSION_GET_PRIVATE(session);
g_return_val_if_fail(s != NULL, FALSE);
- g_return_val_if_fail(fd >= 0, FALSE);
+ g_return_val_if_fail(fd >= -1, FALSE);
spice_session_disconnect(session);
+ s->disconnecting = FALSE;
s->client_provided_sockets = TRUE;
g_warn_if_fail(s->cmain == NULL);
s->cmain = spice_channel_new(session, SPICE_CHANNEL_MAIN, 0);
+
+ glz_decoder_window_clear(s->glz_window);
return spice_channel_open_fd(s->cmain, fd);
}
More information about the Spice-commits
mailing list