[Spice-devel] [PATCH spice-gtk 3/6] Add channel_reset method
Marc-André Lureau
marcandre.lureau at gmail.com
Sun Dec 18 09:27:22 PST 2011
This new private method is to reset the channel to its initial state,
used by semi-seamless migration
---
gtk/channel-cursor.c | 12 ++++++++++
gtk/channel-display.c | 18 ++++++++++++++
gtk/channel-main.c | 41 ++++++++++++++++++++++++++++++++-
gtk/channel-playback.c | 19 +++++++++++++++
gtk/channel-record.c | 21 +++++++++++++++++
gtk/channel-smartcard.c | 56 +++++++++++++++++++++++++++++++++------------
gtk/channel-usbredir.c | 8 ++++++
gtk/spice-channel-priv.h | 2 +
gtk/spice-channel.c | 35 +++++++++++++++++++++-------
gtk/spice-channel.h | 4 ++-
10 files changed, 190 insertions(+), 26 deletions(-)
diff --git a/gtk/channel-cursor.c b/gtk/channel-cursor.c
index 4ad402c..6766b40 100644
--- a/gtk/channel-cursor.c
+++ b/gtk/channel-cursor.c
@@ -92,6 +92,17 @@ static void spice_cursor_channel_finalize(GObject *obj)
G_OBJECT_CLASS(spice_cursor_channel_parent_class)->finalize(obj);
}
+/* coroutine context */
+static void spice_cursor_channel_reset(SpiceChannel *channel, gboolean migrating)
+{
+ SpiceCursorChannelPrivate *c = SPICE_CURSOR_CHANNEL(channel)->priv;
+
+ delete_cursor_all(channel);
+ c->init_done = FALSE;
+
+ SPICE_CHANNEL_CLASS(spice_cursor_channel_parent_class)->channel_reset(channel, migrating);
+}
+
static void spice_cursor_channel_class_init(SpiceCursorChannelClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
@@ -99,6 +110,7 @@ static void spice_cursor_channel_class_init(SpiceCursorChannelClass *klass)
gobject_class->finalize = spice_cursor_channel_finalize;
channel_class->handle_msg = spice_cursor_handle_msg;
+ channel_class->channel_reset = spice_cursor_channel_reset;
/**
* SpiceCursorChannel::cursor-set:
diff --git a/gtk/channel-display.c b/gtk/channel-display.c
index 120128f..47beaa1 100644
--- a/gtk/channel-display.c
+++ b/gtk/channel-display.c
@@ -73,6 +73,7 @@ struct _SpiceDisplayChannelPrivate {
#ifdef WIN32
HDC dc;
#endif
+ gboolean migrate_wait_primary;
};
G_DEFINE_TYPE(SpiceDisplayChannel, spice_display_channel, SPICE_TYPE_CHANNEL)
@@ -103,6 +104,8 @@ static void clear_surfaces(SpiceChannel *channel);
static void clear_streams(SpiceChannel *channel);
static display_surface *find_surface(SpiceDisplayChannelPrivate *c, int surface_id);
static gboolean display_stream_render(display_stream *st);
+static void spice_display_channel_reset(SpiceChannel *channel, gboolean migrating);
+static void destroy_canvas(display_surface *surface);
/* ------------------------------------------------------------------ */
@@ -181,6 +184,20 @@ static void spice_display_set_property(GObject *object,
}
}
+/* main or coroutine context */
+static void spice_display_channel_reset(SpiceChannel *channel, gboolean migrating)
+{
+ SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv;
+
+ /* palettes, images, and glz_window are cleared in the session */
+
+ c->migrate_wait_primary = migrating;
+ clear_streams(channel);
+ clear_surfaces(channel);
+
+ SPICE_CHANNEL_CLASS(spice_display_channel_parent_class)->channel_reset(channel, migrating);
+}
+
static void spice_display_channel_class_init(SpiceDisplayChannelClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
@@ -194,6 +211,7 @@ static void spice_display_channel_class_init(SpiceDisplayChannelClass *klass)
channel_class->handle_msg = spice_display_handle_msg;
channel_class->channel_up = spice_display_channel_up;
+ channel_class->channel_reset = spice_display_channel_reset;
g_object_class_install_property
(gobject_class, PROP_HEIGHT,
diff --git a/gtk/channel-main.c b/gtk/channel-main.c
index 615cdf6..47e41ab 100644
--- a/gtk/channel-main.c
+++ b/gtk/channel-main.c
@@ -122,6 +122,7 @@ static guint signals[SPICE_MAIN_LAST_SIGNAL];
static void spice_main_handle_msg(SpiceChannel *channel, SpiceMsgIn *msg);
static void agent_send_msg_queue(SpiceMainChannel *channel);
+static void agent_free_msg_queue(SpiceMainChannel *channel);
static void migrate_channel_event_cb(SpiceChannel *channel, SpiceChannelEvent event,
gpointer data);
@@ -250,7 +251,7 @@ static void spice_main_channel_finalize(GObject *obj)
SpiceMainChannelPrivate *c = SPICE_MAIN_CHANNEL(obj)->priv;
g_free(c->agent_msg_data);
- g_queue_free(c->agent_msg_queue);
+ agent_free_msg_queue(SPICE_MAIN_CHANNEL(obj));
if (G_OBJECT_CLASS(spice_main_channel_parent_class)->finalize)
G_OBJECT_CLASS(spice_main_channel_parent_class)->finalize(obj);
@@ -265,6 +266,26 @@ static void spice_channel_iterate_write(SpiceChannel *channel)
SPICE_CHANNEL_CLASS(spice_main_channel_parent_class)->iterate_write(channel);
}
+/* main or coroutine context */
+static void spice_main_channel_reset(SpiceChannel *channel, gboolean migrating)
+{
+ SpiceMainChannelPrivate *c = SPICE_MAIN_CHANNEL(channel)->priv;
+
+ c->agent_connected = FALSE;
+ c->agent_caps_received = FALSE;
+ c->agent_display_config_sent = FALSE;
+ c->agent_tokens = 0;
+ c->agent_msg_pos = 0;
+ g_free(c->agent_msg_data);
+ c->agent_msg_data = NULL;
+ c->agent_msg_size = 0;
+
+ agent_free_msg_queue(SPICE_MAIN_CHANNEL(channel));
+ c->agent_msg_queue = g_queue_new();
+
+ SPICE_CHANNEL_CLASS(spice_main_channel_parent_class)->channel_reset(channel, migrating);
+}
+
static void spice_main_channel_class_init(SpiceMainChannelClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
@@ -277,6 +298,7 @@ static void spice_main_channel_class_init(SpiceMainChannelClass *klass)
channel_class->handle_msg = spice_main_handle_msg;
channel_class->iterate_write = spice_channel_iterate_write;
+ channel_class->channel_reset = spice_main_channel_reset;
/**
* SpiceMainChannel:mouse-mode:
@@ -706,6 +728,23 @@ static void do_emit_main_context(GObject *object, int signum, gpointer params)
/* ------------------------------------------------------------------ */
+static void agent_free_msg_queue(SpiceMainChannel *channel)
+{
+ SpiceMainChannelPrivate *c = channel->priv;
+ SpiceMsgOut *out;
+
+ if (!c->agent_msg_queue)
+ return;
+
+ while (!g_queue_is_empty(c->agent_msg_queue)) {
+ out = g_queue_pop_head(c->agent_msg_queue);
+ spice_msg_out_unref(out);
+ }
+
+ g_queue_free(c->agent_msg_queue);
+ c->agent_msg_queue = NULL;
+}
+
/* coroutine context */
static void agent_send_msg_queue(SpiceMainChannel *channel)
{
diff --git a/gtk/channel-playback.c b/gtk/channel-playback.c
index 4804682..32f8b1a 100644
--- a/gtk/channel-playback.c
+++ b/gtk/channel-playback.c
@@ -154,6 +154,24 @@ static void spice_playback_channel_set_property(GObject *gobject,
}
}
+/* main or coroutine context */
+static void spice_playback_channel_reset(SpiceChannel *channel, gboolean migrating)
+{
+ SpicePlaybackChannelPrivate *c = SPICE_PLAYBACK_CHANNEL(channel)->priv;
+
+ if (c->celt_decoder) {
+ celt051_decoder_destroy(c->celt_decoder);
+ c->celt_decoder = NULL;
+ }
+
+ if (c->celt_mode) {
+ celt051_mode_destroy(c->celt_mode);
+ c->celt_mode = NULL;
+ }
+
+ SPICE_CHANNEL_CLASS(spice_playback_channel_parent_class)->channel_reset(channel, migrating);
+}
+
static void spice_playback_channel_class_init(SpicePlaybackChannelClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
@@ -164,6 +182,7 @@ static void spice_playback_channel_class_init(SpicePlaybackChannelClass *klass)
gobject_class->set_property = spice_playback_channel_set_property;
channel_class->handle_msg = spice_playback_handle_msg;
+ channel_class->channel_reset = spice_playback_channel_reset;
g_object_class_install_property
(gobject_class, PROP_NCHANNELS,
diff --git a/gtk/channel-record.c b/gtk/channel-record.c
index 4e5e893..c5aded9 100644
--- a/gtk/channel-record.c
+++ b/gtk/channel-record.c
@@ -163,6 +163,26 @@ static void spice_record_channel_set_property(GObject *gobject,
}
}
+static void channel_reset(SpiceChannel *channel, gboolean migrating)
+{
+ SpiceRecordChannelPrivate *c = SPICE_RECORD_CHANNEL(channel)->priv;
+
+ g_free(c->last_frame);
+ c->last_frame = NULL;
+
+ if (c->celt_encoder) {
+ celt051_encoder_destroy(c->celt_encoder);
+ c->celt_encoder = NULL;
+ }
+
+ if (c->celt_mode) {
+ celt051_mode_destroy(c->celt_mode);
+ c->celt_mode = NULL;
+ }
+
+ SPICE_CHANNEL_CLASS(spice_record_channel_parent_class)->channel_reset(channel, migrating);
+}
+
static void spice_record_channel_class_init(SpiceRecordChannelClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
@@ -173,6 +193,7 @@ static void spice_record_channel_class_init(SpiceRecordChannelClass *klass)
gobject_class->set_property = spice_record_channel_set_property;
channel_class->handle_msg = spice_record_handle_msg;
channel_class->channel_up = channel_up;
+ channel_class->channel_reset = channel_reset;
g_object_class_install_property
(gobject_class, PROP_NCHANNELS,
diff --git a/gtk/channel-smartcard.c b/gtk/channel-smartcard.c
index 98e77eb..6fa4435 100644
--- a/gtk/channel-smartcard.c
+++ b/gtk/channel-smartcard.c
@@ -144,31 +144,56 @@ static void spice_smartcard_channel_init(SpiceSmartcardChannel *channel)
static void spice_smartcard_channel_finalize(GObject *obj)
{
- SpiceSmartcardChannel *channel = SPICE_SMARTCARD_CHANNEL(obj);
+ SpiceSmartcardChannelPrivate *c = SPICE_SMARTCARD_CHANNEL_GET_PRIVATE(obj);
- if (channel->priv->pending_card_insertions != NULL) {
- g_hash_table_destroy(channel->priv->pending_card_insertions);
- channel->priv->pending_card_insertions = NULL;
+ if (c->pending_card_insertions != NULL) {
+ g_hash_table_destroy(c->pending_card_insertions);
+ c->pending_card_insertions = NULL;
}
- if (channel->priv->pending_reader_removals != NULL) {
- g_hash_table_destroy(channel->priv->pending_reader_removals);
- channel->priv->pending_reader_removals = NULL;
+ if (c->pending_reader_removals != NULL) {
+ g_hash_table_destroy(c->pending_reader_removals);
+ c->pending_reader_removals = NULL;
}
- if (channel->priv->message_queue != NULL) {
- g_queue_foreach(channel->priv->message_queue,
- (GFunc)smartcard_message_free, NULL);
- g_queue_free(channel->priv->message_queue);
- channel->priv->message_queue = NULL;
+ if (c->message_queue != NULL) {
+ g_queue_foreach(c->message_queue, (GFunc)smartcard_message_free, NULL);
+ g_queue_free(c->message_queue);
+ c->message_queue = NULL;
}
- if (channel->priv->in_flight_message != NULL) {
- smartcard_message_free(channel->priv->in_flight_message);
- channel->priv->in_flight_message = NULL;
+ if (c->in_flight_message != NULL) {
+ smartcard_message_free(c->in_flight_message);
+ c->in_flight_message = NULL;
}
+ g_list_free(c->pending_reader_additions);
+ c->pending_reader_additions = NULL;
+
if (G_OBJECT_CLASS(spice_smartcard_channel_parent_class)->finalize)
G_OBJECT_CLASS(spice_smartcard_channel_parent_class)->finalize(obj);
}
+static void spice_smartcard_channel_reset(SpiceChannel *channel, gboolean migrating)
+{
+ SpiceSmartcardChannelPrivate *c = SPICE_SMARTCARD_CHANNEL_GET_PRIVATE(channel);
+
+ g_hash_table_remove_all(c->pending_card_insertions);
+ g_hash_table_remove_all(c->pending_reader_removals);
+
+ if (c->message_queue != NULL) {
+ g_queue_foreach(c->message_queue, (GFunc)smartcard_message_free, NULL);
+ g_queue_clear(c->message_queue);
+ }
+
+ if (c->in_flight_message != NULL) {
+ smartcard_message_free(c->in_flight_message);
+ c->in_flight_message = NULL;
+ }
+
+ g_list_free(c->pending_reader_additions);
+ c->pending_reader_additions = NULL;
+
+ SPICE_CHANNEL_CLASS(spice_smartcard_channel_parent_class)->channel_reset(channel, migrating);
+}
+
static void spice_smartcard_channel_class_init(SpiceSmartcardChannelClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
@@ -177,6 +202,7 @@ static void spice_smartcard_channel_class_init(SpiceSmartcardChannelClass *klass
gobject_class->finalize = spice_smartcard_channel_finalize;
channel_class->handle_msg = spice_smartcard_handle_msg;
channel_class->channel_up = spice_smartcard_channel_up;
+ channel_class->channel_reset = spice_smartcard_channel_reset;
g_type_class_add_private(klass, sizeof(SpiceSmartcardChannelPrivate));
}
diff --git a/gtk/channel-usbredir.c b/gtk/channel-usbredir.c
index 06d80d5..cdc04a9 100644
--- a/gtk/channel-usbredir.c
+++ b/gtk/channel-usbredir.c
@@ -102,6 +102,13 @@ static void spice_usbredir_channel_init(SpiceUsbredirChannel *channel)
#endif
}
+static void spice_usbredir_channel_reset(SpiceChannel *channel, gboolean migrating)
+{
+ spice_usbredir_channel_disconnect(SPICE_USBREDIR_CHANNEL(channel));
+
+ SPICE_CHANNEL_CLASS(spice_usbredir_channel_parent_class)->channel_reset(channel, migrating);
+}
+
static void spice_usbredir_channel_class_init(SpiceUsbredirChannelClass *klass)
{
#ifdef USE_USBREDIR
@@ -111,6 +118,7 @@ static void spice_usbredir_channel_class_init(SpiceUsbredirChannelClass *klass)
gobject_class->dispose = spice_usbredir_channel_dispose;
channel_class->handle_msg = spice_usbredir_handle_msg;
channel_class->channel_up = spice_usbredir_channel_up;
+ channel_class->channel_reset = spice_usbredir_channel_reset;
g_type_class_add_private(klass, sizeof(SpiceUsbredirChannelPrivate));
#endif
diff --git a/gtk/spice-channel-priv.h b/gtk/spice-channel-priv.h
index ed5f3a7..5585f13 100644
--- a/gtk/spice-channel-priv.h
+++ b/gtk/spice-channel-priv.h
@@ -166,6 +166,8 @@ void spice_channel_swap(SpiceChannel *channel, SpiceChannel *swap);
void spice_channel_set_common_capability(SpiceChannel *channel, guint32 cap);
gboolean spice_channel_get_read_only(SpiceChannel *channel);
+void spice_channel_reset(SpiceChannel *channel, gboolean migrating);
+
/* coroutine context */
#define emit_main_context(object, event, args...) \
G_STMT_START { \
diff --git a/gtk/spice-channel.c b/gtk/spice-channel.c
index b6779ba..6420c53 100644
--- a/gtk/spice-channel.c
+++ b/gtk/spice-channel.c
@@ -45,6 +45,7 @@ static void spice_channel_handle_msg(SpiceChannel *channel, SpiceMsgIn *msg);
static void spice_channel_write_msg(SpiceChannel *channel, SpiceMsgOut *out);
static void spice_channel_send_link(SpiceChannel *channel);
static void channel_disconnect(SpiceChannel *channel);
+static void channel_reset(SpiceChannel *channel, gboolean migrating);
/**
* SECTION:spice-channel
@@ -249,6 +250,7 @@ static void spice_channel_class_init(SpiceChannelClass *klass)
klass->iterate_write = spice_channel_iterate_write;
klass->iterate_read = spice_channel_iterate_read;
klass->channel_disconnect = channel_disconnect;
+ klass->channel_reset = channel_reset;
gobject_class->constructed = spice_channel_constructed;
gobject_class->dispose = spice_channel_dispose;
@@ -2116,18 +2118,10 @@ gboolean spice_channel_open_fd(SpiceChannel *channel, int fd)
}
/* system or coroutine context */
-static void channel_disconnect(SpiceChannel *channel)
+static void channel_reset(SpiceChannel *channel, gboolean migrating)
{
SpiceChannelPrivate *c = SPICE_CHANNEL_GET_PRIVATE(channel);
- g_return_if_fail(c != NULL);
-
- if (c->state == SPICE_CHANNEL_STATE_UNCONNECTED) {
- return;
- }
-
- c->has_error = TRUE; /* break the loop */
-
if (c->connect_delayed_id) {
g_source_remove(c->connect_delayed_id);
c->connect_delayed_id = 0;
@@ -2174,9 +2168,32 @@ static void channel_disconnect(SpiceChannel *channel)
g_array_set_size(c->caps, 0);
/* Restore our default capabilities in case the channel gets re-used */
spice_channel_set_common_capability(channel, SPICE_COMMON_CAP_PROTOCOL_AUTH_SELECTION);
+}
+
+/* system or coroutine context */
+G_GNUC_INTERNAL
+void spice_channel_reset(SpiceChannel *channel, gboolean migrating)
+{
+ SPICE_CHANNEL_GET_CLASS(channel)->channel_reset(channel, migrating);
+}
+
+/* system or coroutine context */
+static void channel_disconnect(SpiceChannel *channel)
+{
+ SpiceChannelPrivate *c = SPICE_CHANNEL_GET_PRIVATE(channel);
+
+ g_return_if_fail(c != NULL);
+
+ if (c->state == SPICE_CHANNEL_STATE_UNCONNECTED)
+ return;
+
+ c->has_error = TRUE; /* break the loop */
+
+ spice_channel_reset(channel, FALSE);
if (c->state == SPICE_CHANNEL_STATE_READY)
emit_main_context(channel, SPICE_CHANNEL_EVENT, SPICE_CHANNEL_CLOSED);
+
g_return_if_fail(SPICE_IS_CHANNEL(channel));
c->state = SPICE_CHANNEL_STATE_UNCONNECTED;
}
diff --git a/gtk/spice-channel.h b/gtk/spice-channel.h
index 793c5d6..2a8e7e7 100644
--- a/gtk/spice-channel.h
+++ b/gtk/spice-channel.h
@@ -87,11 +87,13 @@ struct _SpiceChannelClass
/*< private >*/
/* virtual method, any context */
void (*channel_disconnect)(SpiceChannel *channel);
+
+ void (*channel_reset)(SpiceChannel *channel, gboolean migrating);
/*
* If adding fields to this struct, remove corresponding
* amount of padding to avoid changing overall struct size
*/
- gchar _spice_reserved[SPICE_RESERVED_PADDING - 4 * sizeof(void*)];
+ gchar _spice_reserved[SPICE_RESERVED_PADDING - 5 * sizeof(void*)];
};
GType spice_channel_get_type(void);
--
1.7.7.4
More information about the Spice-devel
mailing list