[Spice-devel] [PATCH spice-gtk 02/14] channel: use base handlers array

Marc-André Lureau marcandre.lureau at gmail.com
Tue Sep 10 07:44:01 PDT 2013


This allows to simplify a little bit derived class, to avoid overriding
handle_msg, and allows the base class more flexibility (for example for
filtering messages, as in the following patch)
---
 gtk/channel-base.c       | 39 +++++++++++++++++++
 gtk/channel-cursor.c     | 43 ++++++++-------------
 gtk/channel-display.c    | 97 +++++++++++++++++++++---------------------------
 gtk/channel-inputs.c     | 31 +++++-----------
 gtk/channel-main.c       | 60 +++++++++++++++---------------
 gtk/channel-playback.c   | 42 +++++++--------------
 gtk/channel-port.c       | 32 +++++-----------
 gtk/channel-record.c     | 36 ++++++------------
 gtk/channel-smartcard.c  | 21 -----------
 gtk/channel-usbredir.c   | 32 +++++-----------
 gtk/spice-channel-priv.h |  8 +---
 gtk/spice-channel.c      | 18 +++------
 gtk/spice-channel.h      |  3 +-
 13 files changed, 189 insertions(+), 273 deletions(-)

diff --git a/gtk/channel-base.c b/gtk/channel-base.c
index dff3024..76d681a 100644
--- a/gtk/channel-base.c
+++ b/gtk/channel-base.c
@@ -189,3 +189,42 @@ void spice_channel_handle_migrate(SpiceChannel *channel, SpiceMsgIn *in)
         spice_msg_out_send_internal(out);
     }
 }
+
+
+static void set_handlers(SpiceChannelClass *klass,
+                         const spice_msg_handler* handlers, const int n)
+{
+    int i;
+
+    g_array_set_size(klass->handlers, MAX(klass->handlers->len, n));
+    for (i = 0; i < n; i++) {
+        if (handlers[i])
+            g_array_index(klass->handlers, spice_msg_handler, i) = handlers[i];
+    }
+}
+
+static void spice_channel_add_base_handlers(SpiceChannelClass *klass)
+{
+    static const spice_msg_handler handlers[] = {
+        [ SPICE_MSG_SET_ACK ]                  = spice_channel_handle_set_ack,
+        [ SPICE_MSG_PING ]                     = spice_channel_handle_ping,
+        [ SPICE_MSG_NOTIFY ]                   = spice_channel_handle_notify,
+        [ SPICE_MSG_DISCONNECTING ]            = spice_channel_handle_disconnect,
+        [ SPICE_MSG_WAIT_FOR_CHANNELS ]        = spice_channel_handle_wait_for_channels,
+        [ SPICE_MSG_MIGRATE ]                  = spice_channel_handle_migrate,
+    };
+
+    set_handlers(klass, handlers, G_N_ELEMENTS(handlers));
+}
+
+G_GNUC_INTERNAL
+void spice_channel_set_handlers(SpiceChannelClass *klass,
+                                const spice_msg_handler* handlers, const int n)
+{
+    /* FIXME: use class private (requires glib 2.24) */
+    g_return_if_fail(klass->handlers == NULL);
+    klass->handlers = g_array_sized_new(FALSE, TRUE, sizeof(spice_msg_handler), n);
+
+    spice_channel_add_base_handlers(klass);
+    set_handlers(klass, handlers, n);
+}
diff --git a/gtk/channel-cursor.c b/gtk/channel-cursor.c
index e4a996b..5d2db84 100644
--- a/gtk/channel-cursor.c
+++ b/gtk/channel-cursor.c
@@ -66,10 +66,10 @@ enum {
 
 static guint signals[SPICE_CURSOR_LAST_SIGNAL];
 
-static void spice_cursor_handle_msg(SpiceChannel *channel, SpiceMsgIn *msg);
 static void delete_cursor_all(SpiceChannel *channel);
 static display_cursor * display_cursor_ref(display_cursor *cursor);
 static void display_cursor_unref(display_cursor *cursor);
+static void channel_set_handlers(SpiceChannelClass *klass);
 
 G_DEFINE_TYPE(SpiceCursorChannel, spice_cursor_channel, SPICE_TYPE_CHANNEL)
 
@@ -109,7 +109,6 @@ static void spice_cursor_channel_class_init(SpiceCursorChannelClass *klass)
     SpiceChannelClass *channel_class = SPICE_CHANNEL_CLASS(klass);
 
     gobject_class->finalize     = spice_cursor_channel_finalize;
-    channel_class->handle_msg   = spice_cursor_handle_msg;
     channel_class->channel_reset = spice_cursor_channel_reset;
 
     /**
@@ -194,6 +193,7 @@ static void spice_cursor_channel_class_init(SpiceCursorChannelClass *klass)
                      0);
 
     g_type_class_add_private(klass, sizeof(SpiceCursorChannelPrivate));
+    channel_set_handlers(SPICE_CHANNEL_CLASS(klass));
 }
 
 /* signal trampoline---------------------------------------------------------- */
@@ -598,31 +598,18 @@ static void cursor_handle_inval_all(SpiceChannel *channel, SpiceMsgIn *in)
     delete_cursor_all(channel);
 }
 
-static const spice_msg_handler cursor_handlers[] = {
-    [ SPICE_MSG_CURSOR_INIT ]              = cursor_handle_init,
-    [ SPICE_MSG_CURSOR_RESET ]             = cursor_handle_reset,
-    [ SPICE_MSG_CURSOR_SET ]               = cursor_handle_set,
-    [ SPICE_MSG_CURSOR_MOVE ]              = cursor_handle_move,
-    [ SPICE_MSG_CURSOR_HIDE ]              = cursor_handle_hide,
-    [ SPICE_MSG_CURSOR_TRAIL ]             = cursor_handle_trail,
-    [ SPICE_MSG_CURSOR_INVAL_ONE ]         = cursor_handle_inval_one,
-    [ SPICE_MSG_CURSOR_INVAL_ALL ]         = cursor_handle_inval_all,
-};
-
-/* coroutine context */
-static void spice_cursor_handle_msg(SpiceChannel *channel, SpiceMsgIn *msg)
+static void channel_set_handlers(SpiceChannelClass *klass)
 {
-    int type = spice_msg_in_type(msg);
-    SpiceChannelClass *parent_class;
-
-    g_return_if_fail(type < SPICE_N_ELEMENTS(cursor_handlers));
-
-    parent_class = SPICE_CHANNEL_CLASS(spice_cursor_channel_parent_class);
-
-    if (cursor_handlers[type] != NULL)
-        cursor_handlers[type](channel, msg);
-    else if (parent_class->handle_msg)
-        parent_class->handle_msg(channel, msg);
-    else
-        g_return_if_reached();
+    static const spice_msg_handler handlers[] = {
+        [ SPICE_MSG_CURSOR_INIT ]              = cursor_handle_init,
+        [ SPICE_MSG_CURSOR_RESET ]             = cursor_handle_reset,
+        [ SPICE_MSG_CURSOR_SET ]               = cursor_handle_set,
+        [ SPICE_MSG_CURSOR_MOVE ]              = cursor_handle_move,
+        [ SPICE_MSG_CURSOR_HIDE ]              = cursor_handle_hide,
+        [ SPICE_MSG_CURSOR_TRAIL ]             = cursor_handle_trail,
+        [ SPICE_MSG_CURSOR_INVAL_ONE ]         = cursor_handle_inval_one,
+        [ SPICE_MSG_CURSOR_INVAL_ALL ]         = cursor_handle_inval_all,
+    };
+
+    spice_channel_set_handlers(klass, handlers, G_N_ELEMENTS(handlers));
 }
diff --git a/gtk/channel-display.c b/gtk/channel-display.c
index 704d5a7..08d5dcb 100644
--- a/gtk/channel-display.c
+++ b/gtk/channel-display.c
@@ -107,8 +107,8 @@ enum {
 
 static guint signals[SPICE_DISPLAY_LAST_SIGNAL];
 
-static void spice_display_handle_msg(SpiceChannel *channel, SpiceMsgIn *msg);
 static void spice_display_channel_up(SpiceChannel *channel);
+static void channel_set_handlers(SpiceChannelClass *klass);
 
 static void clear_surfaces(SpiceChannel *channel, gboolean keep_primary);
 static void clear_streams(SpiceChannel *channel);
@@ -235,7 +235,6 @@ static void spice_display_channel_class_init(SpiceDisplayChannelClass *klass)
     gobject_class->set_property = spice_display_set_property;
     gobject_class->constructed = spice_display_channel_constructed;
 
-    channel_class->handle_msg   = spice_display_handle_msg;
     channel_class->channel_up   = spice_display_channel_up;
     channel_class->channel_reset = spice_display_channel_reset;
     channel_class->channel_reset_capabilities = spice_display_channel_reset_capabilities;
@@ -387,6 +386,7 @@ static void spice_display_channel_class_init(SpiceDisplayChannelClass *klass)
     sw_canvas_init();
     quic_init();
     rop3_init();
+    channel_set_handlers(SPICE_CHANNEL_CLASS(klass));
 }
 
 /**
@@ -1841,58 +1841,45 @@ static void display_handle_monitors_config(SpiceChannel *channel, SpiceMsgIn *in
     g_object_notify_main_context(G_OBJECT(channel), "monitors");
 }
 
-static const spice_msg_handler display_handlers[] = {
-    [ SPICE_MSG_DISPLAY_MODE ]               = display_handle_mode,
-    [ SPICE_MSG_DISPLAY_MARK ]               = display_handle_mark,
-    [ SPICE_MSG_DISPLAY_RESET ]              = display_handle_reset,
-    [ SPICE_MSG_DISPLAY_COPY_BITS ]          = display_handle_copy_bits,
-    [ SPICE_MSG_DISPLAY_INVAL_LIST ]         = display_handle_inv_list,
-    [ SPICE_MSG_DISPLAY_INVAL_ALL_PIXMAPS ]  = display_handle_inv_pixmap_all,
-    [ SPICE_MSG_DISPLAY_INVAL_PALETTE ]      = display_handle_inv_palette,
-    [ SPICE_MSG_DISPLAY_INVAL_ALL_PALETTES ] = display_handle_inv_palette_all,
-
-    [ SPICE_MSG_DISPLAY_STREAM_CREATE ]      = display_handle_stream_create,
-    [ SPICE_MSG_DISPLAY_STREAM_DATA ]        = display_handle_stream_data,
-    [ SPICE_MSG_DISPLAY_STREAM_CLIP ]        = display_handle_stream_clip,
-    [ SPICE_MSG_DISPLAY_STREAM_DESTROY ]     = display_handle_stream_destroy,
-    [ SPICE_MSG_DISPLAY_STREAM_DESTROY_ALL ] = display_handle_stream_destroy_all,
-    [ SPICE_MSG_DISPLAY_STREAM_DATA_SIZED ]  = display_handle_stream_data,
-    [ SPICE_MSG_DISPLAY_STREAM_ACTIVATE_REPORT ] = display_handle_stream_activate_report,
-
-    [ SPICE_MSG_DISPLAY_DRAW_FILL ]          = display_handle_draw_fill,
-    [ SPICE_MSG_DISPLAY_DRAW_OPAQUE ]        = display_handle_draw_opaque,
-    [ SPICE_MSG_DISPLAY_DRAW_COPY ]          = display_handle_draw_copy,
-    [ SPICE_MSG_DISPLAY_DRAW_BLEND ]         = display_handle_draw_blend,
-    [ SPICE_MSG_DISPLAY_DRAW_BLACKNESS ]     = display_handle_draw_blackness,
-    [ SPICE_MSG_DISPLAY_DRAW_WHITENESS ]     = display_handle_draw_whiteness,
-    [ SPICE_MSG_DISPLAY_DRAW_INVERS ]        = display_handle_draw_invers,
-    [ SPICE_MSG_DISPLAY_DRAW_ROP3 ]          = display_handle_draw_rop3,
-    [ SPICE_MSG_DISPLAY_DRAW_STROKE ]        = display_handle_draw_stroke,
-    [ SPICE_MSG_DISPLAY_DRAW_TEXT ]          = display_handle_draw_text,
-    [ SPICE_MSG_DISPLAY_DRAW_TRANSPARENT ]   = display_handle_draw_transparent,
-    [ SPICE_MSG_DISPLAY_DRAW_ALPHA_BLEND ]   = display_handle_draw_alpha_blend,
-    [ SPICE_MSG_DISPLAY_DRAW_COMPOSITE ]     = display_handle_draw_composite,
-
-    [ SPICE_MSG_DISPLAY_SURFACE_CREATE ]     = display_handle_surface_create,
-    [ SPICE_MSG_DISPLAY_SURFACE_DESTROY ]    = display_handle_surface_destroy,
-
-    [ SPICE_MSG_DISPLAY_MONITORS_CONFIG ]    = display_handle_monitors_config,
-};
-
-/* coroutine context */
-static void spice_display_handle_msg(SpiceChannel *channel, SpiceMsgIn *msg)
-{
-    int type = spice_msg_in_type(msg);
-    SpiceChannelClass *parent_class;
-
-    g_return_if_fail(type < SPICE_N_ELEMENTS(display_handlers));
-
-    parent_class = SPICE_CHANNEL_CLASS(spice_display_channel_parent_class);
+static void channel_set_handlers(SpiceChannelClass *klass)
+{
+    static const spice_msg_handler handlers[] = {
+        [ SPICE_MSG_DISPLAY_MODE ]               = display_handle_mode,
+        [ SPICE_MSG_DISPLAY_MARK ]               = display_handle_mark,
+        [ SPICE_MSG_DISPLAY_RESET ]              = display_handle_reset,
+        [ SPICE_MSG_DISPLAY_COPY_BITS ]          = display_handle_copy_bits,
+        [ SPICE_MSG_DISPLAY_INVAL_LIST ]         = display_handle_inv_list,
+        [ SPICE_MSG_DISPLAY_INVAL_ALL_PIXMAPS ]  = display_handle_inv_pixmap_all,
+        [ SPICE_MSG_DISPLAY_INVAL_PALETTE ]      = display_handle_inv_palette,
+        [ SPICE_MSG_DISPLAY_INVAL_ALL_PALETTES ] = display_handle_inv_palette_all,
+
+        [ SPICE_MSG_DISPLAY_STREAM_CREATE ]      = display_handle_stream_create,
+        [ SPICE_MSG_DISPLAY_STREAM_DATA ]        = display_handle_stream_data,
+        [ SPICE_MSG_DISPLAY_STREAM_CLIP ]        = display_handle_stream_clip,
+        [ SPICE_MSG_DISPLAY_STREAM_DESTROY ]     = display_handle_stream_destroy,
+        [ SPICE_MSG_DISPLAY_STREAM_DESTROY_ALL ] = display_handle_stream_destroy_all,
+        [ SPICE_MSG_DISPLAY_STREAM_DATA_SIZED ]  = display_handle_stream_data,
+        [ SPICE_MSG_DISPLAY_STREAM_ACTIVATE_REPORT ] = display_handle_stream_activate_report,
+
+        [ SPICE_MSG_DISPLAY_DRAW_FILL ]          = display_handle_draw_fill,
+        [ SPICE_MSG_DISPLAY_DRAW_OPAQUE ]        = display_handle_draw_opaque,
+        [ SPICE_MSG_DISPLAY_DRAW_COPY ]          = display_handle_draw_copy,
+        [ SPICE_MSG_DISPLAY_DRAW_BLEND ]         = display_handle_draw_blend,
+        [ SPICE_MSG_DISPLAY_DRAW_BLACKNESS ]     = display_handle_draw_blackness,
+        [ SPICE_MSG_DISPLAY_DRAW_WHITENESS ]     = display_handle_draw_whiteness,
+        [ SPICE_MSG_DISPLAY_DRAW_INVERS ]        = display_handle_draw_invers,
+        [ SPICE_MSG_DISPLAY_DRAW_ROP3 ]          = display_handle_draw_rop3,
+        [ SPICE_MSG_DISPLAY_DRAW_STROKE ]        = display_handle_draw_stroke,
+        [ SPICE_MSG_DISPLAY_DRAW_TEXT ]          = display_handle_draw_text,
+        [ SPICE_MSG_DISPLAY_DRAW_TRANSPARENT ]   = display_handle_draw_transparent,
+        [ SPICE_MSG_DISPLAY_DRAW_ALPHA_BLEND ]   = display_handle_draw_alpha_blend,
+        [ SPICE_MSG_DISPLAY_DRAW_COMPOSITE ]     = display_handle_draw_composite,
+
+        [ SPICE_MSG_DISPLAY_SURFACE_CREATE ]     = display_handle_surface_create,
+        [ SPICE_MSG_DISPLAY_SURFACE_DESTROY ]    = display_handle_surface_destroy,
+
+        [ SPICE_MSG_DISPLAY_MONITORS_CONFIG ]    = display_handle_monitors_config,
+    };
 
-    if (display_handlers[type] != NULL)
-        display_handlers[type](channel, msg);
-    else if (parent_class->handle_msg)
-        parent_class->handle_msg(channel, msg);
-    else
-        g_return_if_reached();
+    spice_channel_set_handlers(klass, handlers, G_N_ELEMENTS(handlers));
 }
diff --git a/gtk/channel-inputs.c b/gtk/channel-inputs.c
index ee86dc2..a69dbe6 100644
--- a/gtk/channel-inputs.c
+++ b/gtk/channel-inputs.c
@@ -67,9 +67,9 @@ enum {
 
 static guint signals[SPICE_INPUTS_LAST_SIGNAL];
 
-static void spice_inputs_handle_msg(SpiceChannel *channel, SpiceMsgIn *msg);
 static void spice_inputs_channel_up(SpiceChannel *channel);
 static void spice_inputs_channel_reset(SpiceChannel *channel, gboolean migrating);
+static void channel_set_handlers(SpiceChannelClass *klass);
 
 /* ------------------------------------------------------------------ */
 
@@ -108,7 +108,6 @@ static void spice_inputs_channel_class_init(SpiceInputsChannelClass *klass)
 
     gobject_class->finalize     = spice_inputs_channel_finalize;
     gobject_class->get_property = spice_inputs_get_property;
-    channel_class->handle_msg   = spice_inputs_handle_msg;
     channel_class->channel_up   = spice_inputs_channel_up;
     channel_class->channel_reset = spice_inputs_channel_reset;
 
@@ -143,6 +142,7 @@ static void spice_inputs_channel_class_init(SpiceInputsChannelClass *klass)
                      0);
 
     g_type_class_add_private(klass, sizeof(SpiceInputsChannelPrivate));
+    channel_set_handlers(SPICE_CHANNEL_CLASS(klass));
 }
 
 /* signal trampoline---------------------------------------------------------- */
@@ -281,28 +281,15 @@ static void inputs_handle_ack(SpiceChannel *channel, SpiceMsgIn *in)
     }
 }
 
-static const spice_msg_handler inputs_handlers[] = {
-    [ SPICE_MSG_INPUTS_INIT ]              = inputs_handle_init,
-    [ SPICE_MSG_INPUTS_KEY_MODIFIERS ]     = inputs_handle_modifiers,
-    [ SPICE_MSG_INPUTS_MOUSE_MOTION_ACK ]  = inputs_handle_ack,
-};
-
-/* coroutine context */
-static void spice_inputs_handle_msg(SpiceChannel *channel, SpiceMsgIn *msg)
+static void channel_set_handlers(SpiceChannelClass *klass)
 {
-    int type = spice_msg_in_type(msg);
-    SpiceChannelClass *parent_class;
-
-    g_return_if_fail(type < SPICE_N_ELEMENTS(inputs_handlers));
-
-    parent_class = SPICE_CHANNEL_CLASS(spice_inputs_channel_parent_class);
+    static const spice_msg_handler handlers[] = {
+        [ SPICE_MSG_INPUTS_INIT ]              = inputs_handle_init,
+        [ SPICE_MSG_INPUTS_KEY_MODIFIERS ]     = inputs_handle_modifiers,
+        [ SPICE_MSG_INPUTS_MOUSE_MOTION_ACK ]  = inputs_handle_ack,
+    };
 
-    if (inputs_handlers[type] != NULL)
-        inputs_handlers[type](channel, msg);
-    else if (parent_class->handle_msg)
-        parent_class->handle_msg(channel, msg);
-    else
-        g_return_if_reached();
+    spice_channel_set_handlers(klass, handlers, G_N_ELEMENTS(handlers));
 }
 
 /**
diff --git a/gtk/channel-main.c b/gtk/channel-main.c
index 93995f1..b342e97 100644
--- a/gtk/channel-main.c
+++ b/gtk/channel-main.c
@@ -158,6 +158,7 @@ enum {
 static guint signals[SPICE_MAIN_LAST_SIGNAL];
 
 static void spice_main_handle_msg(SpiceChannel *channel, SpiceMsgIn *msg);
+static void channel_set_handlers(SpiceChannelClass *klass);
 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,
@@ -728,6 +729,7 @@ static void spice_main_channel_class_init(SpiceMainChannelClass *klass)
                      G_TYPE_OBJECT);
 
     g_type_class_add_private(klass, sizeof(SpiceMainChannelPrivate));
+    channel_set_handlers(SPICE_CHANNEL_CLASS(klass));
 }
 
 /* signal trampoline---------------------------------------------------------- */
@@ -2316,28 +2318,33 @@ static void main_handle_migrate_cancel(SpiceChannel *channel,
     spice_session_abort_migration(session);
 }
 
-static const spice_msg_handler main_handlers[] = {
-    [ SPICE_MSG_MAIN_INIT ]                = main_handle_init,
-    [ SPICE_MSG_MAIN_NAME ]                = main_handle_name,
-    [ SPICE_MSG_MAIN_UUID ]                = main_handle_uuid,
-    [ SPICE_MSG_MAIN_CHANNELS_LIST ]       = main_handle_channels_list,
-    [ SPICE_MSG_MAIN_MOUSE_MODE ]          = main_handle_mouse_mode,
-    [ SPICE_MSG_MAIN_MULTI_MEDIA_TIME ]    = main_handle_mm_time,
-
-    [ SPICE_MSG_MAIN_AGENT_CONNECTED ]     = main_handle_agent_connected,
-    [ SPICE_MSG_MAIN_AGENT_DISCONNECTED ]  = main_handle_agent_disconnected,
-    [ SPICE_MSG_MAIN_AGENT_DATA ]          = main_handle_agent_data,
-    [ SPICE_MSG_MAIN_AGENT_TOKEN ]         = main_handle_agent_token,
-
-    [ SPICE_MSG_MAIN_MIGRATE_BEGIN ]       = main_handle_migrate_begin,
-    [ SPICE_MSG_MAIN_MIGRATE_END ]         = main_handle_migrate_end,
-    [ SPICE_MSG_MAIN_MIGRATE_CANCEL ]      = main_handle_migrate_cancel,
-    [ SPICE_MSG_MAIN_MIGRATE_SWITCH_HOST ] = main_handle_migrate_switch_host,
-    [ SPICE_MSG_MAIN_AGENT_CONNECTED_TOKENS ]   = main_handle_agent_connected_tokens,
-    [ SPICE_MSG_MAIN_MIGRATE_BEGIN_SEAMLESS ]   = main_handle_migrate_begin_seamless,
-    [ SPICE_MSG_MAIN_MIGRATE_DST_SEAMLESS_ACK]  = main_handle_migrate_dst_seamless_ack,
-    [ SPICE_MSG_MAIN_MIGRATE_DST_SEAMLESS_NACK] = main_handle_migrate_dst_seamless_nack,
-};
+static void channel_set_handlers(SpiceChannelClass *klass)
+{
+    static const spice_msg_handler handlers[] = {
+        [ SPICE_MSG_MAIN_INIT ]                = main_handle_init,
+        [ SPICE_MSG_MAIN_NAME ]                = main_handle_name,
+        [ SPICE_MSG_MAIN_UUID ]                = main_handle_uuid,
+        [ SPICE_MSG_MAIN_CHANNELS_LIST ]       = main_handle_channels_list,
+        [ SPICE_MSG_MAIN_MOUSE_MODE ]          = main_handle_mouse_mode,
+        [ SPICE_MSG_MAIN_MULTI_MEDIA_TIME ]    = main_handle_mm_time,
+
+        [ SPICE_MSG_MAIN_AGENT_CONNECTED ]     = main_handle_agent_connected,
+        [ SPICE_MSG_MAIN_AGENT_DISCONNECTED ]  = main_handle_agent_disconnected,
+        [ SPICE_MSG_MAIN_AGENT_DATA ]          = main_handle_agent_data,
+        [ SPICE_MSG_MAIN_AGENT_TOKEN ]         = main_handle_agent_token,
+
+        [ SPICE_MSG_MAIN_MIGRATE_BEGIN ]       = main_handle_migrate_begin,
+        [ SPICE_MSG_MAIN_MIGRATE_END ]         = main_handle_migrate_end,
+        [ SPICE_MSG_MAIN_MIGRATE_CANCEL ]      = main_handle_migrate_cancel,
+        [ SPICE_MSG_MAIN_MIGRATE_SWITCH_HOST ] = main_handle_migrate_switch_host,
+        [ SPICE_MSG_MAIN_AGENT_CONNECTED_TOKENS ]   = main_handle_agent_connected_tokens,
+        [ SPICE_MSG_MAIN_MIGRATE_BEGIN_SEAMLESS ]   = main_handle_migrate_begin_seamless,
+        [ SPICE_MSG_MAIN_MIGRATE_DST_SEAMLESS_ACK]  = main_handle_migrate_dst_seamless_ack,
+        [ SPICE_MSG_MAIN_MIGRATE_DST_SEAMLESS_NACK] = main_handle_migrate_dst_seamless_nack,
+    };
+
+    spice_channel_set_handlers(klass, handlers, G_N_ELEMENTS(handlers));
+}
 
 /* coroutine context */
 static void spice_main_handle_msg(SpiceChannel *channel, SpiceMsgIn *msg)
@@ -2346,8 +2353,6 @@ static void spice_main_handle_msg(SpiceChannel *channel, SpiceMsgIn *msg)
     SpiceChannelClass *parent_class;
     SpiceChannelPrivate *c = SPICE_CHANNEL(channel)->priv;
 
-    g_return_if_fail(type < SPICE_N_ELEMENTS(main_handlers));
-
     parent_class = SPICE_CHANNEL_CLASS(spice_main_channel_parent_class);
 
     if (c->state == SPICE_CHANNEL_STATE_MIGRATION_HANDSHAKE) {
@@ -2359,12 +2364,7 @@ static void spice_main_handle_msg(SpiceChannel *channel, SpiceMsgIn *msg)
         }
     }
 
-    if (main_handlers[type] != NULL)
-        main_handlers[type](channel, msg);
-    else if (parent_class->handle_msg)
-        parent_class->handle_msg(channel, msg);
-    else
-        g_return_if_reached();
+    parent_class->handle_msg(channel, msg);
 }
 
 /**
diff --git a/gtk/channel-playback.c b/gtk/channel-playback.c
index f246a80..60fc113 100644
--- a/gtk/channel-playback.c
+++ b/gtk/channel-playback.c
@@ -82,8 +82,7 @@ enum {
 };
 
 static guint signals[SPICE_PLAYBACK_LAST_SIGNAL];
-
-static void spice_playback_handle_msg(SpiceChannel *channel, SpiceMsgIn *msg);
+static void channel_set_handlers(SpiceChannelClass *klass);
 
 /* ------------------------------------------------------------------ */
 
@@ -197,7 +196,6 @@ static void spice_playback_channel_class_init(SpicePlaybackChannelClass *klass)
     gobject_class->get_property = spice_playback_channel_get_property;
     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;
     channel_class->channel_reset_capabilities = spice_playback_channel_reset_capabilities;
 
@@ -308,6 +306,7 @@ static void spice_playback_channel_class_init(SpicePlaybackChannelClass *klass)
                      0);
 
     g_type_class_add_private(klass, sizeof(SpicePlaybackChannelPrivate));
+    channel_set_handlers(SPICE_CHANNEL_CLASS(klass));
 }
 
 /* signal trampoline---------------------------------------------------------- */
@@ -517,32 +516,19 @@ static void playback_handle_set_latency(SpiceChannel *channel, SpiceMsgIn *in)
     g_object_notify_main_context(G_OBJECT(channel), "min-latency");
 }
 
-static const spice_msg_handler playback_handlers[] = {
-    [ SPICE_MSG_PLAYBACK_DATA ]            = playback_handle_data,
-    [ SPICE_MSG_PLAYBACK_MODE ]            = playback_handle_mode,
-    [ SPICE_MSG_PLAYBACK_START ]           = playback_handle_start,
-    [ SPICE_MSG_PLAYBACK_STOP ]            = playback_handle_stop,
-    [ SPICE_MSG_PLAYBACK_VOLUME ]          = playback_handle_set_volume,
-    [ SPICE_MSG_PLAYBACK_MUTE ]            = playback_handle_set_mute,
-    [ SPICE_MSG_PLAYBACK_LATENCY ]         = playback_handle_set_latency,
-};
-
-/* coroutine context */
-static void spice_playback_handle_msg(SpiceChannel *channel, SpiceMsgIn *msg)
+static void channel_set_handlers(SpiceChannelClass *klass)
 {
-    int type = spice_msg_in_type(msg);
-    SpiceChannelClass *parent_class;
-
-    g_return_if_fail(type < SPICE_N_ELEMENTS(playback_handlers));
-
-    parent_class = SPICE_CHANNEL_CLASS(spice_playback_channel_parent_class);
-
-    if (playback_handlers[type] != NULL)
-        playback_handlers[type](channel, msg);
-    else if (parent_class->handle_msg)
-        parent_class->handle_msg(channel, msg);
-    else
-        g_return_if_reached();
+    static const spice_msg_handler handlers[] = {
+        [ SPICE_MSG_PLAYBACK_DATA ]            = playback_handle_data,
+        [ SPICE_MSG_PLAYBACK_MODE ]            = playback_handle_mode,
+        [ SPICE_MSG_PLAYBACK_START ]           = playback_handle_start,
+        [ SPICE_MSG_PLAYBACK_STOP ]            = playback_handle_stop,
+        [ SPICE_MSG_PLAYBACK_VOLUME ]          = playback_handle_set_volume,
+        [ SPICE_MSG_PLAYBACK_MUTE ]            = playback_handle_set_mute,
+        [ SPICE_MSG_PLAYBACK_LATENCY ]         = playback_handle_set_latency,
+    };
+
+    spice_channel_set_handlers(klass, handlers, G_N_ELEMENTS(handlers));
 }
 
 void spice_playback_channel_set_delay(SpicePlaybackChannel *channel, guint32 delay_ms)
diff --git a/gtk/channel-port.c b/gtk/channel-port.c
index 1d6eef2..11948bb 100644
--- a/gtk/channel-port.c
+++ b/gtk/channel-port.c
@@ -76,8 +76,7 @@ enum {
 };
 
 static guint signals[LAST_SIGNAL];
-
-static void spice_port_handle_msg(SpiceChannel *channel, SpiceMsgIn *msg);
+static void channel_set_handlers(SpiceChannelClass *klass);
 
 static void spice_port_channel_init(SpicePortChannel *channel)
 {
@@ -131,7 +130,6 @@ static void spice_port_channel_class_init(SpicePortChannelClass *klass)
 
     gobject_class->finalize     = spice_port_channel_finalize;
     gobject_class->get_property = spice_port_get_property;
-    channel_class->handle_msg   = spice_port_handle_msg;
     channel_class->channel_reset = spice_port_channel_reset;
 
     g_object_class_install_property
@@ -194,6 +192,7 @@ static void spice_port_channel_class_init(SpicePortChannelClass *klass)
                      G_TYPE_INT);
 
     g_type_class_add_private(klass, sizeof(SpicePortChannelPrivate));
+    channel_set_handlers(SPICE_CHANNEL_CLASS(klass));
 }
 
 /* signal trampoline---------------------------------------------------------- */
@@ -401,26 +400,13 @@ void spice_port_event(SpicePortChannel *self, guint8 event)
     spice_msg_out_send(msg);
 }
 
-static const spice_msg_handler port_handlers[] = {
-    [ SPICE_MSG_PORT_INIT ]              = port_handle_init,
-    [ SPICE_MSG_PORT_EVENT ]             = port_handle_event,
-    [ SPICE_MSG_SPICEVMC_DATA ]          = port_handle_msg,
-};
-
-/* coroutine context */
-static void spice_port_handle_msg(SpiceChannel *channel, SpiceMsgIn *msg)
+static void channel_set_handlers(SpiceChannelClass *klass)
 {
-    int type = spice_msg_in_type(msg);
-    SpiceChannelClass *parent_class;
-
-    g_return_if_fail(type < SPICE_N_ELEMENTS(port_handlers));
-
-    parent_class = SPICE_CHANNEL_CLASS(spice_port_channel_parent_class);
+    static const spice_msg_handler handlers[] = {
+        [ SPICE_MSG_PORT_INIT ]              = port_handle_init,
+        [ SPICE_MSG_PORT_EVENT ]             = port_handle_event,
+        [ SPICE_MSG_SPICEVMC_DATA ]          = port_handle_msg,
+    };
 
-    if (port_handlers[type] != NULL)
-        port_handlers[type](channel, msg);
-    else if (parent_class->handle_msg)
-        parent_class->handle_msg(channel, msg);
-    else
-        g_return_if_reached();
+    spice_channel_set_handlers(klass, handlers, G_N_ELEMENTS(handlers));
 }
diff --git a/gtk/channel-record.c b/gtk/channel-record.c
index 6345569..e1f3ec7 100644
--- a/gtk/channel-record.c
+++ b/gtk/channel-record.c
@@ -81,7 +81,7 @@ enum {
 
 static guint signals[SPICE_RECORD_LAST_SIGNAL];
 
-static void spice_record_handle_msg(SpiceChannel *channel, SpiceMsgIn *msg);
+static void channel_set_handlers(SpiceChannelClass *klass);
 static void channel_up(SpiceChannel *channel);
 
 #define FRAME_SIZE 256
@@ -197,7 +197,6 @@ static void spice_record_channel_class_init(SpiceRecordChannelClass *klass)
     gobject_class->finalize     = spice_record_channel_finalize;
     gobject_class->get_property = spice_record_channel_get_property;
     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;
     channel_class->channel_reset_capabilities = spice_record_channel_reset_capabilities;
@@ -265,6 +264,7 @@ static void spice_record_channel_class_init(SpiceRecordChannelClass *klass)
                      0);
 
     g_type_class_add_private(klass, sizeof(SpiceRecordChannelPrivate));
+    channel_set_handlers(SPICE_CHANNEL_CLASS(klass));
 }
 
 /* signal trampoline---------------------------------------------------------- */
@@ -521,28 +521,14 @@ static void record_handle_set_mute(SpiceChannel *channel, SpiceMsgIn *in)
     g_object_notify_main_context(G_OBJECT(channel), "mute");
 }
 
-static const spice_msg_handler record_handlers[] = {
-    [ SPICE_MSG_RECORD_START ]             = record_handle_start,
-    [ SPICE_MSG_RECORD_STOP ]              = record_handle_stop,
-    [ SPICE_MSG_RECORD_VOLUME ]            = record_handle_set_volume,
-    [ SPICE_MSG_RECORD_MUTE ]              = record_handle_set_mute,
-};
-
-/* coroutine context */
-static void spice_record_handle_msg(SpiceChannel *channel, SpiceMsgIn *msg)
+static void channel_set_handlers(SpiceChannelClass *klass)
 {
-    int type = spice_msg_in_type(msg);
-
-    SpiceChannelClass *parent_class;
-
-    g_return_if_fail(type < SPICE_N_ELEMENTS(record_handlers));
-
-    parent_class = SPICE_CHANNEL_CLASS(spice_record_channel_parent_class);
-
-    if (record_handlers[type] != NULL)
-        record_handlers[type](channel, msg);
-    else if (parent_class->handle_msg)
-        parent_class->handle_msg(channel, msg);
-    else
-        g_return_if_reached();
+    static const spice_msg_handler handlers[] = {
+        [ SPICE_MSG_RECORD_START ]             = record_handle_start,
+        [ SPICE_MSG_RECORD_STOP ]              = record_handle_stop,
+        [ SPICE_MSG_RECORD_VOLUME ]            = record_handle_set_volume,
+        [ SPICE_MSG_RECORD_MUTE ]              = record_handle_set_mute,
+    };
+
+    spice_channel_set_handlers(klass, handlers, G_N_ELEMENTS(handlers));
 }
diff --git a/gtk/channel-smartcard.c b/gtk/channel-smartcard.c
index 21b8343..0b5e050 100644
--- a/gtk/channel-smartcard.c
+++ b/gtk/channel-smartcard.c
@@ -95,7 +95,6 @@ enum {
     SPICE_SMARTCARD_LAST_SIGNAL,
 };
 
-static void spice_smartcard_handle_msg(SpiceChannel *channel, SpiceMsgIn *msg);
 static void spice_smartcard_channel_up(SpiceChannel *channel);
 static void handle_smartcard_msg(SpiceChannel *channel, SpiceMsgIn *in);
 static void smartcard_message_free(SpiceSmartcardChannelMessage *message);
@@ -217,7 +216,6 @@ static void spice_smartcard_channel_class_init(SpiceSmartcardChannelClass *klass
     gobject_class->finalize     = spice_smartcard_channel_finalize;
     gobject_class->constructed  = spice_smartcard_channel_constructed;
 
-    channel_class->handle_msg   = spice_smartcard_handle_msg;
     channel_class->channel_up   = spice_smartcard_channel_up;
     channel_class->channel_reset = spice_smartcard_channel_reset;
 
@@ -442,24 +440,6 @@ static void card_removed_cb(SpiceSmartcardManager *manager, VReader *reader,
 }
 #endif /* USE_SMARTCARD */
 
-/* coroutine context */
-static void spice_smartcard_handle_msg(SpiceChannel *channel, SpiceMsgIn *msg)
-{
-    int type = spice_msg_in_type(msg);
-    SpiceChannelClass *parent_class;
-
-    g_return_if_fail(type < SPICE_N_ELEMENTS(smartcard_handlers));
-
-    parent_class = SPICE_CHANNEL_CLASS(spice_smartcard_channel_parent_class);
-
-    if (smartcard_handlers[type] != NULL)
-        smartcard_handlers[type](channel, msg);
-    else if (parent_class->handle_msg)
-        parent_class->handle_msg(channel, msg);
-    else
-        g_return_if_reached();
-}
-
 static void spice_smartcard_channel_up_cb(GObject *source_object,
                                           GAsyncResult *res,
                                           gpointer user_data)
@@ -570,4 +550,3 @@ static void handle_smartcard_msg(SpiceChannel *channel, SpiceMsgIn *in)
     }
 #endif
 }
-
diff --git a/gtk/channel-usbredir.c b/gtk/channel-usbredir.c
index 11bf38c..239fe12 100644
--- a/gtk/channel-usbredir.c
+++ b/gtk/channel-usbredir.c
@@ -81,7 +81,7 @@ struct _SpiceUsbredirChannelPrivate {
 #endif
 };
 
-static void spice_usbredir_handle_msg(SpiceChannel *channel, SpiceMsgIn *msg);
+static void channel_set_handlers(SpiceChannelClass *klass);
 static void spice_usbredir_channel_up(SpiceChannel *channel);
 static void spice_usbredir_channel_dispose(GObject *obj);
 static void spice_usbredir_channel_finalize(GObject *obj);
@@ -136,11 +136,11 @@ static void spice_usbredir_channel_class_init(SpiceUsbredirChannelClass *klass)
 
     gobject_class->dispose       = spice_usbredir_channel_dispose;
     gobject_class->finalize      = spice_usbredir_channel_finalize;
-    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));
+    channel_set_handlers(SPICE_CHANNEL_CLASS(klass));
 #endif
 }
 
@@ -188,9 +188,14 @@ static void spice_usbredir_channel_finalize(GObject *obj)
         G_OBJECT_CLASS(spice_usbredir_channel_parent_class)->finalize(obj);
 }
 
-static const spice_msg_handler usbredir_handlers[] = {
-    [ SPICE_MSG_SPICEVMC_DATA ] = usbredir_handle_msg,
-};
+static void channel_set_handlers(SpiceChannelClass *klass)
+{
+    static const spice_msg_handler handlers[] = {
+        [ SPICE_MSG_SPICEVMC_DATA ] = usbredir_handle_msg,
+    };
+
+    spice_channel_set_handlers(klass, handlers, G_N_ELEMENTS(handlers));
+}
 
 /* ------------------------------------------------------------------ */
 /* private api                                                        */
@@ -608,23 +613,6 @@ static void do_emit_main_context(GObject *object, int event, gpointer params)
 
 /* --------------------------------------------------------------------- */
 /* coroutine context                                                     */
-static void spice_usbredir_handle_msg(SpiceChannel *c, SpiceMsgIn *msg)
-{
-    int type = spice_msg_in_type(msg);
-    SpiceChannelClass *parent_class;
-
-    g_return_if_fail(type < SPICE_N_ELEMENTS(usbredir_handlers));
-
-    parent_class = SPICE_CHANNEL_CLASS(spice_usbredir_channel_parent_class);
-
-    if (usbredir_handlers[type] != NULL)
-        usbredir_handlers[type](c, msg);
-    else if (parent_class->handle_msg)
-        parent_class->handle_msg(c, msg);
-    else
-        g_return_if_reached();
-}
-
 static void spice_usbredir_channel_up(SpiceChannel *c)
 {
     SpiceUsbredirChannel *channel = SPICE_USBREDIR_CHANNEL(c);
diff --git a/gtk/spice-channel-priv.h b/gtk/spice-channel-priv.h
index be061c5..92c9315 100644
--- a/gtk/spice-channel-priv.h
+++ b/gtk/spice-channel-priv.h
@@ -167,13 +167,9 @@ typedef void (*handler_msg_in)(SpiceChannel *channel, SpiceMsgIn *msg, gpointer
 void spice_channel_recv_msg(SpiceChannel *channel, handler_msg_in handler, gpointer data);
 
 /* channel-base.c */
-/* coroutine context */
-void spice_channel_handle_set_ack(SpiceChannel *channel, SpiceMsgIn *in);
-void spice_channel_handle_ping(SpiceChannel *channel, SpiceMsgIn *in);
-void spice_channel_handle_notify(SpiceChannel *channel, SpiceMsgIn *in);
-void spice_channel_handle_disconnect(SpiceChannel *channel, SpiceMsgIn *in);
+void spice_channel_set_handlers(SpiceChannelClass *klass,
+                                const spice_msg_handler* handlers, const int n);
 void spice_channel_handle_wait_for_channels(SpiceChannel *channel, SpiceMsgIn *in);
-void spice_channel_handle_migrate(SpiceChannel *channel, SpiceMsgIn *in);
 
 gint spice_channel_get_channel_id(SpiceChannel *channel);
 gint spice_channel_get_channel_type(SpiceChannel *channel);
diff --git a/gtk/spice-channel.c b/gtk/spice-channel.c
index 093b292..a0d9c15 100644
--- a/gtk/spice-channel.c
+++ b/gtk/spice-channel.c
@@ -2763,24 +2763,18 @@ void spice_channel_swap(SpiceChannel *channel, SpiceChannel *swap, gboolean swap
 #endif
 }
 
-static const spice_msg_handler base_handlers[] = {
-    [ SPICE_MSG_SET_ACK ]                  = spice_channel_handle_set_ack,
-    [ SPICE_MSG_PING ]                     = spice_channel_handle_ping,
-    [ SPICE_MSG_NOTIFY ]                   = spice_channel_handle_notify,
-    [ SPICE_MSG_DISCONNECTING ]            = spice_channel_handle_disconnect,
-    [ SPICE_MSG_WAIT_FOR_CHANNELS ]        = spice_channel_handle_wait_for_channels,
-    [ SPICE_MSG_MIGRATE ]                  = spice_channel_handle_migrate,
-};
-
 /* coroutine context */
 static void spice_channel_handle_msg(SpiceChannel *channel, SpiceMsgIn *msg)
 {
+    SpiceChannelClass *klass = SPICE_CHANNEL_GET_CLASS(channel);
     int type = spice_msg_in_type(msg);
+    spice_msg_handler handler;
 
-    g_return_if_fail(type < SPICE_N_ELEMENTS(base_handlers));
-    g_return_if_fail(base_handlers[type] != NULL);
+    g_return_if_fail(type < klass->handlers->len);
 
-    base_handlers[type](channel, msg);
+    handler = g_array_index(klass->handlers, spice_msg_handler, type);
+    g_return_if_fail(handler != NULL);
+    handler(channel, msg);
 }
 
 static void spice_channel_reset_capabilities(SpiceChannel *channel)
diff --git a/gtk/spice-channel.h b/gtk/spice-channel.h
index 0507b68..705dddf 100644
--- a/gtk/spice-channel.h
+++ b/gtk/spice-channel.h
@@ -94,11 +94,12 @@ struct _SpiceChannelClass
     /* virtual methods, coroutine context */
     void (*channel_send_migration_handshake)(SpiceChannel *channel);
 
+    GArray                      *handlers;
     /*
      * If adding fields to this struct, remove corresponding
      * amount of padding to avoid changing overall struct size
      */
-    gchar _spice_reserved[SPICE_RESERVED_PADDING - sizeof(void *)];
+    gchar _spice_reserved[SPICE_RESERVED_PADDING - 2 * sizeof(void *)];
 };
 
 GType spice_channel_get_type(void);
-- 
1.8.3.1



More information about the Spice-devel mailing list