2 Copyright (C) 2010 Red Hat, Inc.
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, see <http://www.gnu.org/licenses/>.
25 #include <glib/gi18n.h>
27 #include <spice-client.h>
28 #include <spice-util.h>
29 #include <channel-display.h>
33 static void shutdown (self_t *self);
34 static int click (struct self_t *self, int x, int y, int b);
38 static char *tls_port;
39 static char *password;
42 static char *host_subject;
43 static char *smartcard_db;
44 static char *smartcard_certificates;
45 static gboolean smartcard = FALSE;
47 static GOptionEntry spice_entries[] = {
49 .long_name = "spice-uri",
50 .arg = G_OPTION_ARG_STRING,
52 .description = N_("Spice server uri"),
53 .arg_description = N_("<uri>"),
55 .long_name = "spice-host",
56 .arg = G_OPTION_ARG_STRING,
58 .description = N_("Spice server address"),
59 .arg_description = N_("<host>"),
61 .long_name = "spice-port",
62 .arg = G_OPTION_ARG_STRING,
64 .description = N_("Spice server port"),
65 .arg_description = N_("<port>"),
67 .long_name = "spice-secure-port",
68 .arg = G_OPTION_ARG_STRING,
69 .arg_data = &tls_port,
70 .description = N_("Spice server secure port"),
71 .arg_description = N_("<port>"),
73 .long_name = "spice-ca-file",
74 .arg = G_OPTION_ARG_FILENAME,
76 .description = N_("Truststore file for secure connections"),
77 .arg_description = N_("<file>"),
79 .long_name = "spice-password",
80 .arg = G_OPTION_ARG_STRING,
81 .arg_data = &password,
82 .description = N_("Server password"),
83 .arg_description = N_("<password>"),
85 .long_name = "spice-host-subject",
86 .arg = G_OPTION_ARG_STRING,
87 .arg_data = &host_subject,
88 .description = N_("Subject of the host certificate (field=value pairs separated by commas)"),
89 .arg_description = N_("<host-subject>"),
95 static GOptionGroup *spice_group;
98 vc_spice_cmdline_get_option_group(void)
100 if (spice_group == NULL) {
101 spice_group = g_option_group_new("spice",
103 _("Show spice Options"),
105 g_option_group_add_entries(spice_group, spice_entries);
111 primary_create (SpiceChannel *channel, gint format,
112 gint width, gint height, gint stride,
113 gint shmid, gpointer imgdata, gpointer opaque)
115 self_t *self = opaque;
118 fprintf (stderr, "Connected to spice server (primary display channel)\n");
120 /* Remember that we managed to connect. */
121 self->connected = TRUE;
123 vc_issue_command (self);
127 channel_new (SpiceSession *s, SpiceChannel *channel, gpointer opaque)
129 self_t *self = opaque;
131 if (SPICE_IS_INPUTS_CHANNEL (channel))
132 self->inputs_channel = channel;
133 if (SPICE_IS_DISPLAY_CHANNEL (channel))
134 self->display_channel = channel;
136 if (SPICE_IS_DISPLAY_CHANNEL (channel))
137 g_signal_connect (channel, "display-primary-create",
138 G_CALLBACK (primary_create), self);
139 spice_channel_connect (channel);
142 static callbacks_t callbacks = {
144 .shutdown = shutdown,
148 vc_spice_setup (self_t *self)
151 spice_util_set_debug (TRUE);
153 self->callbacks = &callbacks;
155 self->session = spice_session_new ();
156 g_signal_connect (self->session, "channel-new",
157 G_CALLBACK(channel_new), self);
159 if (ca_file == NULL) {
160 const char *homedir = g_getenv("HOME");
162 homedir = g_get_home_dir();
163 ca_file = g_strdup_printf("%s/.spicec/spice_truststore.pem", homedir);
167 g_object_set(self->session, "uri", uri, NULL);
169 g_object_set(self->session, "host", host, NULL);
171 g_object_set(self->session, "port", port, NULL);
173 g_object_set(self->session, "tls-port", tls_port, NULL);
175 g_object_set(self->session, "password", password, NULL);
177 g_object_set(self->session, "ca-file", ca_file, NULL);
179 g_object_set(self->session, "cert-subject", host_subject, NULL);
181 if (!spice_session_connect (self->session)) {
182 fprintf (stderr, _("spice: session connection failed\n"));
188 vc_spice_is_selected (void)
190 return uri != NULL || host != NULL;
194 get_channel_id (SpiceChannel *channel)
197 g_object_get (channel, "channel-id", &id, NULL);
203 shutdown (self_t *self)
205 spice_session_disconnect (self->session);
206 g_object_unref (self->session);
210 click (struct self_t *self, int x, int y, int b)
212 int id = get_channel_id (self->display_channel);
214 spice_inputs_position (SPICE_INPUTS_CHANNEL (self->inputs_channel),
218 case 0: b = 0; break;
219 case 1: b = SPICE_MOUSE_BUTTON_LEFT; break;
220 case 2: b = SPICE_MOUSE_BUTTON_MIDDLE; break;
221 case 3: b = SPICE_MOUSE_BUTTON_RIGHT; break;
222 case 4: b = SPICE_MOUSE_BUTTON_UP; break;
223 case 5: b = SPICE_MOUSE_BUTTON_DOWN; break;
225 fprintf (stderr, "spice: button %d is not supported\n", b);
230 spice_inputs_button_press (SPICE_INPUTS_CHANNEL (self->inputs_channel),