[Spice-commits] 2 commits - gtk/channel-cursor.c gtk/channel-display.c gtk/channel-inputs.c gtk/channel-main.c gtk/channel-playback.c gtk/channel-port.c gtk/channel-record.c gtk/channel-usbredir.c gtk/gio-coroutine.c gtk/gio-coroutine.h gtk/spice-channel-priv.h gtk/spice-channel.c gtk/spice-session.c

Marc-André Lureau elmarco at kemper.freedesktop.org
Wed Jun 11 06:47:12 PDT 2014


 gtk/channel-cursor.c     |   66 +++-------------------
 gtk/channel-display.c    |   84 +++++-----------------------
 gtk/channel-inputs.c     |   22 -------
 gtk/channel-main.c       |  139 +++++------------------------------------------
 gtk/channel-playback.c   |   64 +++------------------
 gtk/channel-port.c       |   39 +------------
 gtk/channel-record.c     |   40 +------------
 gtk/channel-usbredir.c   |   49 ++++++++--------
 gtk/gio-coroutine.c      |   70 +++++++++++------------
 gtk/gio-coroutine.h      |    7 +-
 gtk/spice-channel-priv.h |   11 ---
 gtk/spice-channel.c      |   61 ++++++--------------
 gtk/spice-session.c      |   25 +-------
 13 files changed, 146 insertions(+), 531 deletions(-)

New commits:
commit 0f4459d0658467a5f1ec4c41c7bdc57fb2cb6ca2
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Thu May 29 23:20:00 2014 +0200

    Remove coroutine trampolines
    
    Use va_list instead of an ugly trampoline hack

diff --git a/gtk/channel-cursor.c b/gtk/channel-cursor.c
index d7242a6..fb19536 100644
--- a/gtk/channel-cursor.c
+++ b/gtk/channel-cursor.c
@@ -200,52 +200,6 @@ static void spice_cursor_channel_class_init(SpiceCursorChannelClass *klass)
     channel_set_handlers(SPICE_CHANNEL_CLASS(klass));
 }
 
-/* signal trampoline---------------------------------------------------------- */
-
-struct SPICE_CURSOR_HIDE {
-};
-
-struct SPICE_CURSOR_RESET {
-};
-
-struct SPICE_CURSOR_SET {
-    uint16_t width;
-    uint16_t height;
-    uint16_t hot_spot_x;
-    uint16_t hot_spot_y;
-    gpointer rgba;
-};
-
-struct SPICE_CURSOR_MOVE {
-    gint x;
-    gint y;
-};
-
-/* main context */
-static void do_emit_main_context(GObject *object, int signum, gpointer params)
-{
-    switch (signum) {
-    case SPICE_CURSOR_HIDE:
-    case SPICE_CURSOR_RESET: {
-        g_signal_emit(object, signals[signum], 0);
-        break;
-    }
-    case SPICE_CURSOR_SET: {
-        struct SPICE_CURSOR_SET *p = params;
-        g_signal_emit(object, signals[signum], 0,
-                      p->width, p->height, p->hot_spot_x, p->hot_spot_y, p->rgba);
-        break;
-    }
-    case SPICE_CURSOR_MOVE: {
-        struct SPICE_CURSOR_MOVE *p = params;
-        g_signal_emit(object, signals[signum], 0, p->x, p->y);
-        break;
-    }
-    default:
-        g_warn_if_reached();
-    }
-}
-
 /* ------------------------------------------------------------------ */
 
 #ifdef DEBUG_CURSOR
@@ -446,10 +400,10 @@ cache_add:
 static void emit_cursor_set(SpiceChannel *channel, display_cursor *cursor)
 {
     g_return_if_fail(cursor != NULL);
-    emit_main_context(channel, SPICE_CURSOR_SET,
-                      cursor->hdr.width, cursor->hdr.height,
-                      cursor->hdr.hot_spot_x, cursor->hdr.hot_spot_y,
-                      cursor->default_cursor ? NULL : cursor->data);
+    g_coroutine_signal_emit(channel, signals[SPICE_CURSOR_SET], 0,
+                            cursor->hdr.width, cursor->hdr.height,
+                            cursor->hdr.hot_spot_x, cursor->hdr.hot_spot_y,
+                            cursor->default_cursor ? NULL : cursor->data);
 }
 
 /* coroutine context */
@@ -467,7 +421,7 @@ static void cursor_handle_init(SpiceChannel *channel, SpiceMsgIn *in)
     if (cursor)
         emit_cursor_set(channel, cursor);
     if (!init->visible || !cursor)
-        emit_main_context(channel, SPICE_CURSOR_HIDE);
+        g_coroutine_signal_emit(channel, signals[SPICE_CURSOR_HIDE], 0);
     if (cursor)
         display_cursor_unref(cursor);
 }
@@ -480,7 +434,7 @@ static void cursor_handle_reset(SpiceChannel *channel, SpiceMsgIn *in)
     CHANNEL_DEBUG(channel, "%s, init_done: %d", __FUNCTION__, c->init_done);
 
     cache_clear(c->cursors);
-    emit_main_context(channel, SPICE_CURSOR_RESET);
+    g_coroutine_signal_emit(channel, signals[SPICE_CURSOR_RESET], 0);
     c->init_done = FALSE;
 }
 
@@ -497,7 +451,7 @@ static void cursor_handle_set(SpiceChannel *channel, SpiceMsgIn *in)
     if (cursor)
         emit_cursor_set(channel, cursor);
     else
-        emit_main_context(channel, SPICE_CURSOR_HIDE);
+        g_coroutine_signal_emit(channel, signals[SPICE_CURSOR_HIDE], 0);
 
 
     if (cursor)
@@ -512,8 +466,8 @@ static void cursor_handle_move(SpiceChannel *channel, SpiceMsgIn *in)
 
     g_return_if_fail(c->init_done == TRUE);
 
-    emit_main_context(channel, SPICE_CURSOR_MOVE,
-                      move->position.x, move->position.y);
+    g_coroutine_signal_emit(channel, signals[SPICE_CURSOR_MOVE], 0,
+                            move->position.x, move->position.y);
 }
 
 /* coroutine context */
@@ -525,7 +479,7 @@ static void cursor_handle_hide(SpiceChannel *channel, SpiceMsgIn *in)
     g_return_if_fail(c->init_done == TRUE);
 #endif
 
-    emit_main_context(channel, SPICE_CURSOR_HIDE);
+    g_coroutine_signal_emit(channel, signals[SPICE_CURSOR_HIDE], 0);
 }
 
 /* coroutine context */
diff --git a/gtk/channel-display.c b/gtk/channel-display.c
index ff9f85c..6265334 100644
--- a/gtk/channel-display.c
+++ b/gtk/channel-display.c
@@ -429,60 +429,6 @@ gboolean spice_display_get_primary(SpiceChannel *channel, guint32 surface_id,
     return TRUE;
 }
 
-/* signal trampoline---------------------------------------------------------- */
-
-struct SPICE_DISPLAY_PRIMARY_CREATE {
-    gint format;
-    gint width;
-    gint height;
-    gint stride;
-    gint shmid;
-    gpointer imgdata;
-};
-
-struct SPICE_DISPLAY_PRIMARY_DESTROY {
-};
-
-struct SPICE_DISPLAY_INVALIDATE {
-    gint x;
-    gint y;
-    gint w;
-    gint h;
-};
-
-struct SPICE_DISPLAY_MARK {
-    gint mark;
-};
-
-/* main context */
-static void do_emit_main_context(GObject *object, int signum, gpointer params)
-{
-    switch (signum) {
-    case SPICE_DISPLAY_PRIMARY_DESTROY: {
-        g_signal_emit(object, signals[signum], 0);
-        break;
-    }
-    case SPICE_DISPLAY_MARK: {
-        struct SPICE_DISPLAY_MARK *p = params;
-        g_signal_emit(object, signals[signum], 0, p->mark);
-        break;
-    }
-    case SPICE_DISPLAY_PRIMARY_CREATE: {
-        struct SPICE_DISPLAY_PRIMARY_CREATE *p = params;
-        g_signal_emit(object, signals[signum], 0,
-                      p->format, p->width, p->height, p->stride, p->shmid, p->imgdata);
-        break;
-    }
-    case SPICE_DISPLAY_INVALIDATE: {
-        struct SPICE_DISPLAY_INVALIDATE *p = params;
-        g_signal_emit(object, signals[signum], 0, p->x, p->y, p->w, p->h);
-        break;
-    }
-    default:
-        g_warn_if_reached();
-    }
-}
-
 /* ------------------------------------------------------------------ */
 
 static void image_put(SpiceImageCache *cache, uint64_t id, pixman_image_t *image)
@@ -701,7 +647,7 @@ static int create_canvas(SpiceChannel *channel, display_surface *surface)
                 return 0;
             }
 
-            emit_main_context(channel, SPICE_DISPLAY_PRIMARY_DESTROY);
+            g_coroutine_signal_emit(channel, signals[SPICE_DISPLAY_PRIMARY_DESTROY], 0);
 
             g_hash_table_remove(c->surfaces, GINT_TO_POINTER(c->primary->surface_id));
         }
@@ -757,9 +703,9 @@ static int create_canvas(SpiceChannel *channel, display_surface *surface)
     if (surface->primary) {
         g_warn_if_fail(c->primary == NULL);
         c->primary = surface;
-        emit_main_context(channel, SPICE_DISPLAY_PRIMARY_CREATE,
-                          surface->format, surface->width, surface->height,
-                          surface->stride, surface->shmid, surface->data);
+        g_coroutine_signal_emit(channel, signals[SPICE_DISPLAY_PRIMARY_CREATE], 0,
+                                surface->format, surface->width, surface->height,
+                                surface->stride, surface->shmid, surface->data);
 
         if (!spice_channel_test_capability(channel, SPICE_DISPLAY_CAP_MONITORS_CONFIG)) {
             g_array_set_size(c->monitors, 1);
@@ -767,7 +713,7 @@ static int create_canvas(SpiceChannel *channel, display_surface *surface)
             config->x = config->y = 0;
             config->width = surface->width;
             config->height = surface->height;
-            g_object_notify_main_context(G_OBJECT(channel), "monitors");
+            g_coroutine_object_notify(G_OBJECT(channel), "monitors");
         }
     }
 
@@ -816,7 +762,7 @@ static void clear_surfaces(SpiceChannel *channel, gboolean keep_primary)
 
     if (!keep_primary) {
         c->primary = NULL;
-        emit_main_context(channel, SPICE_DISPLAY_PRIMARY_DESTROY);
+        g_coroutine_signal_emit(channel, signals[SPICE_DISPLAY_PRIMARY_DESTROY], 0);
     }
 
     g_hash_table_iter_init(&iter, c->surfaces);
@@ -834,10 +780,10 @@ static void clear_surfaces(SpiceChannel *channel, gboolean keep_primary)
 /* coroutine context */
 static void emit_invalidate(SpiceChannel *channel, SpiceRect *bbox)
 {
-    emit_main_context(channel, SPICE_DISPLAY_INVALIDATE,
-                      bbox->left, bbox->top,
-                      bbox->right - bbox->left,
-                      bbox->bottom - bbox->top);
+    g_coroutine_signal_emit(channel, signals[SPICE_DISPLAY_INVALIDATE], 0,
+                            bbox->left, bbox->top,
+                            bbox->right - bbox->left,
+                            bbox->bottom - bbox->top);
 }
 
 /* ------------------------------------------------------------------ */
@@ -868,7 +814,7 @@ static void spice_display_channel_up(SpiceChannel *channel)
     /* if we are not using monitors config, notify of existence of
        this monitor */
     if (channel->priv->channel_id != 0)
-        g_object_notify_main_context(G_OBJECT(channel), "monitors");
+        g_coroutine_object_notify(G_OBJECT(channel), "monitors");
 }
 
 #define DRAW(type) {                                                    \
@@ -915,7 +861,7 @@ static void display_handle_mark(SpiceChannel *channel, SpiceMsgIn *in)
 #endif
 
     c->mark = TRUE;
-    emit_main_context(channel, SPICE_DISPLAY_MARK, TRUE);
+    g_coroutine_signal_emit(channel, signals[SPICE_DISPLAY_MARK], 0, TRUE);
 }
 
 /* coroutine context */
@@ -932,7 +878,7 @@ static void display_handle_reset(SpiceChannel *channel, SpiceMsgIn *in)
     cache_clear(c->palettes);
 
     c->mark = FALSE;
-    emit_main_context(channel, SPICE_DISPLAY_MARK, FALSE);
+    g_coroutine_signal_emit(channel, signals[SPICE_DISPLAY_MARK], 0, FALSE);
 }
 
 /* coroutine context */
@@ -1753,7 +1699,7 @@ static void display_handle_surface_destroy(SpiceChannel *channel, SpiceMsgIn *in
             c->mark_false_event_id = g_timeout_add_seconds(1, display_mark_false, channel);
         }
         c->primary = NULL;
-        emit_main_context(channel, SPICE_DISPLAY_PRIMARY_DESTROY);
+        g_coroutine_signal_emit(channel, signals[SPICE_DISPLAY_PRIMARY_DESTROY], 0);
     }
 
     g_hash_table_remove(c->surfaces, GINT_TO_POINTER(surface->surface_id));
@@ -1800,7 +1746,7 @@ static void display_handle_monitors_config(SpiceChannel *channel, SpiceMsgIn *in
         mc->height = head->height;
     }
 
-    g_object_notify_main_context(G_OBJECT(channel), "monitors");
+    g_coroutine_object_notify(G_OBJECT(channel), "monitors");
 }
 
 static void channel_set_handlers(SpiceChannelClass *klass)
diff --git a/gtk/channel-inputs.c b/gtk/channel-inputs.c
index 8a726e0..70e7b25 100644
--- a/gtk/channel-inputs.c
+++ b/gtk/channel-inputs.c
@@ -147,24 +147,6 @@ static void spice_inputs_channel_class_init(SpiceInputsChannelClass *klass)
     channel_set_handlers(SPICE_CHANNEL_CLASS(klass));
 }
 
-/* signal trampoline---------------------------------------------------------- */
-
-struct SPICE_INPUTS_MODIFIERS {
-};
-
-/* main context */
-static void do_emit_main_context(GObject *object, int signum, gpointer params)
-{
-    switch (signum) {
-    case SPICE_INPUTS_MODIFIERS: {
-        g_signal_emit(object, signals[signum], 0);
-        break;
-    }
-    default:
-        g_warn_if_reached();
-    }
-}
-
 /* ------------------------------------------------------------------ */
 
 static SpiceMsgOut* mouse_motion(SpiceInputsChannel *channel)
@@ -251,7 +233,7 @@ static void inputs_handle_init(SpiceChannel *channel, SpiceMsgIn *in)
     SpiceMsgInputsInit *init = spice_msg_in_parsed(in);
 
     c->modifiers = init->keyboard_modifiers;
-    emit_main_context(channel, SPICE_INPUTS_MODIFIERS);
+    g_coroutine_signal_emit(channel, signals[SPICE_INPUTS_MODIFIERS], 0);
 }
 
 /* coroutine context */
@@ -261,7 +243,7 @@ static void inputs_handle_modifiers(SpiceChannel *channel, SpiceMsgIn *in)
     SpiceMsgInputsKeyModifiers *modifiers = spice_msg_in_parsed(in);
 
     c->modifiers = modifiers->modifiers;
-    emit_main_context(channel, SPICE_INPUTS_MODIFIERS);
+    g_coroutine_signal_emit(channel, signals[SPICE_INPUTS_MODIFIERS], 0);
 }
 
 /* coroutine context */
diff --git a/gtk/channel-main.c b/gtk/channel-main.c
index 58f5d31..352499c 100644
--- a/gtk/channel-main.c
+++ b/gtk/channel-main.c
@@ -808,115 +808,6 @@ static void spice_main_channel_class_init(SpiceMainChannelClass *klass)
     channel_set_handlers(SPICE_CHANNEL_CLASS(klass));
 }
 
-/* signal trampoline---------------------------------------------------------- */
-
-struct SPICE_MAIN_CLIPBOARD_RELEASE {
-};
-
-struct SPICE_MAIN_AGENT_UPDATE {
-};
-
-struct SPICE_MAIN_MOUSE_UPDATE {
-};
-
-struct SPICE_MAIN_CLIPBOARD {
-    guint type;
-    gpointer data;
-    gsize size;
-};
-
-struct SPICE_MAIN_CLIPBOARD_GRAB {
-    gpointer types;
-    gsize ntypes;
-    gboolean *ret;
-};
-
-struct SPICE_MAIN_CLIPBOARD_REQUEST {
-    guint type;
-    gboolean *ret;
-};
-
-struct SPICE_MAIN_CLIPBOARD_SELECTION {
-    guint8 selection;
-    guint type;
-    gpointer data;
-    gsize size;
-};
-
-struct SPICE_MAIN_CLIPBOARD_SELECTION_GRAB {
-    guint8 selection;
-    gpointer types;
-    gsize ntypes;
-    gboolean *ret;
-};
-
-struct SPICE_MAIN_CLIPBOARD_SELECTION_REQUEST {
-    guint8 selection;
-    guint type;
-    gboolean *ret;
-};
-
-struct SPICE_MAIN_CLIPBOARD_SELECTION_RELEASE {
-    guint8 selection;
-};
-
-/* main context */
-static void do_emit_main_context(GObject *object, int signum, gpointer params)
-{
-    switch (signum) {
-    case SPICE_MAIN_CLIPBOARD_RELEASE:
-    case SPICE_MAIN_AGENT_UPDATE:
-    case SPICE_MAIN_MOUSE_UPDATE: {
-        g_signal_emit(object, signals[signum], 0);
-        break;
-    }
-    case SPICE_MAIN_CLIPBOARD: {
-        struct SPICE_MAIN_CLIPBOARD *p = params;
-        g_signal_emit(object, signals[signum], 0,
-                      p->type, p->data, p->size);
-        break;
-    }
-    case SPICE_MAIN_CLIPBOARD_GRAB: {
-        struct SPICE_MAIN_CLIPBOARD_GRAB *p = params;
-        g_signal_emit(object, signals[signum], 0,
-                      p->types, p->ntypes, p->ret);
-        break;
-    }
-    case SPICE_MAIN_CLIPBOARD_REQUEST: {
-        struct SPICE_MAIN_CLIPBOARD_REQUEST *p = params;
-        g_signal_emit(object, signals[signum], 0,
-                      p->type, p->ret);
-        break;
-    }
-    case SPICE_MAIN_CLIPBOARD_SELECTION: {
-        struct SPICE_MAIN_CLIPBOARD_SELECTION *p = params;
-        g_signal_emit(object, signals[signum], 0,
-                      p->selection, p->type, p->data, p->size);
-        break;
-    }
-    case SPICE_MAIN_CLIPBOARD_SELECTION_GRAB: {
-        struct SPICE_MAIN_CLIPBOARD_SELECTION_GRAB *p = params;
-        g_signal_emit(object, signals[signum], 0,
-                      p->selection, p->types, p->ntypes, p->ret);
-        break;
-    }
-    case SPICE_MAIN_CLIPBOARD_SELECTION_REQUEST: {
-        struct SPICE_MAIN_CLIPBOARD_SELECTION_REQUEST *p = params;
-        g_signal_emit(object, signals[signum], 0,
-                      p->selection, p->type, p->ret);
-        break;
-    }
-    case SPICE_MAIN_CLIPBOARD_SELECTION_RELEASE: {
-        struct SPICE_MAIN_CLIPBOARD_SELECTION_RELEASE *p = params;
-        g_signal_emit(object, signals[signum], 0,
-                      p->selection);
-        break;
-    }
-    default:
-        g_warn_if_reached();
-    }
-}
-
 /* ------------------------------------------------------------------ */
 
 
@@ -1437,12 +1328,12 @@ static void set_agent_connected(SpiceMainChannel *channel, gboolean connected)
     SPICE_DEBUG("agent connected: %s", spice_yes_no(connected));
     if (connected != c->agent_connected) {
         c->agent_connected = connected;
-        g_object_notify_main_context(G_OBJECT(channel), "agent-connected");
+        g_coroutine_object_notify(G_OBJECT(channel), "agent-connected");
     }
     if (!connected)
         spice_main_channel_reset_agent(SPICE_MAIN_CHANNEL(channel));
 
-    emit_main_context(channel, SPICE_MAIN_AGENT_UPDATE);
+    g_coroutine_signal_emit(channel, signals[SPICE_MAIN_AGENT_UPDATE], 0);
 }
 
 /* coroutine context  */
@@ -1480,8 +1371,8 @@ static void set_mouse_mode(SpiceMainChannel *channel, uint32_t supported, uint32
 
     if (c->mouse_mode != current) {
         c->mouse_mode = current;
-        emit_main_context(channel, SPICE_MAIN_MOUSE_UPDATE);
-        g_object_notify_main_context(G_OBJECT(channel), "mouse-mode");
+        g_coroutine_signal_emit(channel, signals[SPICE_MAIN_MOUSE_UPDATE], 0);
+        g_coroutine_object_notify(G_OBJECT(channel), "mouse-mode");
     }
 
     /* switch to client mode if possible */
@@ -1590,7 +1481,7 @@ static void main_handle_channels_list(SpiceChannel *channel, SpiceMsgIn *in)
 
     /* guarantee that uuid is notified before setting up the channels, even if
      * the server is older and doesn't actually send the uuid */
-    g_object_notify_main_context(G_OBJECT(session), "uuid");
+    g_coroutine_object_notify(G_OBJECT(session), "uuid");
 
     for (i = 0; i < msg->num_of_channels; i++) {
         channel_new_t *c;
@@ -1898,7 +1789,7 @@ static void main_agent_handle_msg(SpiceChannel *channel,
             VD_AGENT_SET_CAPABILITY(c->agent_caps, i);
         }
         c->agent_caps_received = true;
-        emit_main_context(self, SPICE_MAIN_AGENT_UPDATE);
+        g_coroutine_signal_emit(self, signals[SPICE_MAIN_AGENT_UPDATE], 0);
 
         if (caps->request)
             agent_announce_caps(self);
@@ -1918,21 +1809,21 @@ static void main_agent_handle_msg(SpiceChannel *channel,
     case VD_AGENT_CLIPBOARD:
     {
         VDAgentClipboard *cb = payload;
-        emit_main_context(self, SPICE_MAIN_CLIPBOARD_SELECTION, selection,
-                          cb->type, cb->data, msg->size - sizeof(VDAgentClipboard));
+        g_coroutine_signal_emit(self, signals[SPICE_MAIN_CLIPBOARD_SELECTION], 0, selection,
+                                cb->type, cb->data, msg->size - sizeof(VDAgentClipboard));
 
        if (selection == VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD)
-            emit_main_context(self, SPICE_MAIN_CLIPBOARD,
+           g_coroutine_signal_emit(self, signals[SPICE_MAIN_CLIPBOARD], 0,
                               cb->type, cb->data, msg->size - sizeof(VDAgentClipboard));
         break;
     }
     case VD_AGENT_CLIPBOARD_GRAB:
     {
         gboolean ret;
-        emit_main_context(self, SPICE_MAIN_CLIPBOARD_SELECTION_GRAB, selection,
+        g_coroutine_signal_emit(self, signals[SPICE_MAIN_CLIPBOARD_SELECTION_GRAB], 0, selection,
                           (guint8*)payload, msg->size / sizeof(uint32_t), &ret);
         if (selection == VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD)
-            emit_main_context(self, SPICE_MAIN_CLIPBOARD_GRAB,
+            g_coroutine_signal_emit(self, signals[SPICE_MAIN_CLIPBOARD_GRAB], 0,
                               payload, msg->size / sizeof(uint32_t), &ret);
         break;
     }
@@ -1940,20 +1831,20 @@ static void main_agent_handle_msg(SpiceChannel *channel,
     {
         gboolean ret;
         VDAgentClipboardRequest *req = payload;
-        emit_main_context(self, SPICE_MAIN_CLIPBOARD_SELECTION_REQUEST, selection,
+        g_coroutine_signal_emit(self, signals[SPICE_MAIN_CLIPBOARD_SELECTION_REQUEST], 0, selection,
                           req->type, &ret);
 
         if (selection == VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD)
-            emit_main_context(self, SPICE_MAIN_CLIPBOARD_REQUEST,
+            g_coroutine_signal_emit(self, signals[SPICE_MAIN_CLIPBOARD_REQUEST], 0,
                               req->type, &ret);
         break;
     }
     case VD_AGENT_CLIPBOARD_RELEASE:
     {
-        emit_main_context(self, SPICE_MAIN_CLIPBOARD_SELECTION_RELEASE, selection);
+        g_coroutine_signal_emit(self, signals[SPICE_MAIN_CLIPBOARD_SELECTION_RELEASE], 0, selection);
 
         if (selection == VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD)
-            emit_main_context(self, SPICE_MAIN_CLIPBOARD_RELEASE);
+            g_coroutine_signal_emit(self, signals[SPICE_MAIN_CLIPBOARD_RELEASE], 0);
         break;
     }
     case VD_AGENT_REPLY:
diff --git a/gtk/channel-playback.c b/gtk/channel-playback.c
index 7789aa8..e5b9658 100644
--- a/gtk/channel-playback.c
+++ b/gtk/channel-playback.c
@@ -298,52 +298,6 @@ static void spice_playback_channel_class_init(SpicePlaybackChannelClass *klass)
     channel_set_handlers(SPICE_CHANNEL_CLASS(klass));
 }
 
-/* signal trampoline---------------------------------------------------------- */
-
-struct SPICE_PLAYBACK_START {
-    gint format;
-    gint channels;
-    gint frequency;
-    gint latency;
-};
-
-struct SPICE_PLAYBACK_DATA {
-    uint8_t *data;
-    gsize data_size;
-};
-
-struct SPICE_PLAYBACK_STOP {
-};
-
-struct SPICE_PLAYBACK_GET_DELAY {
-};
-
-/* main context */
-static void do_emit_main_context(GObject *object, int signum, gpointer params)
-{
-    switch (signum) {
-    case SPICE_PLAYBACK_GET_DELAY:
-    case SPICE_PLAYBACK_STOP: {
-        g_signal_emit(object, signals[signum], 0);
-        break;
-    }
-    case SPICE_PLAYBACK_START: {
-        struct SPICE_PLAYBACK_START *p = params;
-        g_signal_emit(object, signals[signum], 0,
-                      p->format, p->channels, p->frequency);
-        break;
-    }
-    case SPICE_PLAYBACK_DATA: {
-        struct SPICE_PLAYBACK_DATA *p = params;
-        g_signal_emit(object, signals[signum], 0,
-                      p->data, p->data_size);
-        break;
-    }
-    default:
-        g_warn_if_reached();
-    }
-}
-
 /* ------------------------------------------------------------------ */
 
 /* coroutine context */
@@ -377,10 +331,10 @@ static void playback_handle_data(SpiceChannel *channel, SpiceMsgIn *in)
         }
     }
 
-    emit_main_context(channel, SPICE_PLAYBACK_DATA, data, n);
+    g_coroutine_signal_emit(channel, signals[SPICE_PLAYBACK_DATA], 0, data, n);
 
     if ((c->frame_count++ % 100) == 0) {
-        emit_main_context(channel, SPICE_PLAYBACK_GET_DELAY);
+        g_coroutine_signal_emit(channel, signals[SPICE_PLAYBACK_GET_DELAY], 0);
     }
 }
 
@@ -426,8 +380,8 @@ static void playback_handle_start(SpiceChannel *channel, SpiceMsgIn *in)
             return;
         }
     }
-    emit_main_context(channel, SPICE_PLAYBACK_START,
-         start->format, start->channels, start->frequency);
+    g_coroutine_signal_emit(channel, signals[SPICE_PLAYBACK_START], 0,
+                            start->format, start->channels, start->frequency);
 }
 
 /* coroutine context */
@@ -435,7 +389,7 @@ static void playback_handle_stop(SpiceChannel *channel, SpiceMsgIn *in)
 {
     SpicePlaybackChannelPrivate *c = SPICE_PLAYBACK_CHANNEL(channel)->priv;
 
-    emit_main_context(channel, SPICE_PLAYBACK_STOP);
+    g_coroutine_signal_emit(channel, signals[SPICE_PLAYBACK_STOP], 0);
     c->is_active = FALSE;
 }
 
@@ -454,7 +408,7 @@ static void playback_handle_set_volume(SpiceChannel *channel, SpiceMsgIn *in)
     c->nchannels = vol->nchannels;
     c->volume = g_new(guint16, c->nchannels);
     memcpy(c->volume, vol->volume, sizeof(guint16) * c->nchannels);
-    g_object_notify_main_context(G_OBJECT(channel), "volume");
+    g_coroutine_object_notify(G_OBJECT(channel), "volume");
 }
 
 /* coroutine context */
@@ -464,7 +418,7 @@ static void playback_handle_set_mute(SpiceChannel *channel, SpiceMsgIn *in)
     SpiceMsgAudioMute *m = spice_msg_in_parsed(in);
 
     c->mute = m->mute;
-    g_object_notify_main_context(G_OBJECT(channel), "mute");
+    g_coroutine_object_notify(G_OBJECT(channel), "mute");
 }
 
 /* coroutine context */
@@ -475,7 +429,7 @@ static void playback_handle_set_latency(SpiceChannel *channel, SpiceMsgIn *in)
 
     c->min_latency = msg->latency_ms;
     SPICE_DEBUG("%s: notify latency update %u", __FUNCTION__, c->min_latency);
-    g_object_notify_main_context(G_OBJECT(channel), "min-latency");
+    g_coroutine_object_notify(G_OBJECT(channel), "min-latency");
 }
 
 static void channel_set_handlers(SpiceChannelClass *klass)
@@ -530,5 +484,5 @@ void spice_playback_channel_sync_latency(SpicePlaybackChannel *channel)
     g_return_if_fail(SPICE_IS_PLAYBACK_CHANNEL(channel));
     g_return_if_fail(channel->priv->is_active);
     SPICE_DEBUG("%s: notify latency update %u", __FUNCTION__, channel->priv->min_latency);
-    g_object_notify_main_context(G_OBJECT(SPICE_CHANNEL(channel)), "min-latency");
+    g_coroutine_object_notify(G_OBJECT(SPICE_CHANNEL(channel)), "min-latency");
 }
diff --git a/gtk/channel-port.c b/gtk/channel-port.c
index ad85afd..f0b6d1e 100644
--- a/gtk/channel-port.c
+++ b/gtk/channel-port.c
@@ -197,35 +197,6 @@ static void spice_port_channel_class_init(SpicePortChannelClass *klass)
     channel_set_handlers(SPICE_CHANNEL_CLASS(klass));
 }
 
-/* signal trampoline---------------------------------------------------------- */
-
-struct SPICE_PORT_DATA {
-    uint8_t *data;
-    gsize data_size;
-};
-
-struct SPICE_PORT_EVENT {
-    int event;
-};
-
-/* main context */
-static void do_emit_main_context(GObject *object, int signum, gpointer params)
-{
-    switch (signum) {
-    case SPICE_PORT_DATA: {
-        struct SPICE_PORT_DATA *p = params;
-        g_signal_emit(object, signals[signum], 0, p->data, p->data_size);
-        break;
-    }
-    case SPICE_PORT_EVENT: {
-        struct SPICE_PORT_EVENT *p = params;
-        g_signal_emit(object, signals[signum], 0, p->event);
-        break;
-    }
-    default:
-        g_warn_if_reached();
-    }
-}
 
 /* coroutine context */
 static void port_set_opened(SpicePortChannel *self, gboolean opened)
@@ -236,7 +207,7 @@ static void port_set_opened(SpicePortChannel *self, gboolean opened)
         return;
 
     c->opened = opened;
-    g_object_notify_main_context(G_OBJECT(self), "port-opened");
+    g_coroutine_object_notify(G_OBJECT(self), "port-opened");
 }
 
 /* coroutine context */
@@ -254,9 +225,9 @@ static void port_handle_init(SpiceChannel *channel, SpiceMsgIn *in)
 
     port_set_opened(self, init->opened);
     if (init->opened)
-        emit_main_context(channel, SPICE_PORT_EVENT, SPICE_PORT_EVENT_OPENED);
+        g_coroutine_signal_emit(channel, signals[SPICE_PORT_EVENT], 0, SPICE_PORT_EVENT_OPENED);
 
-    g_object_notify_main_context(G_OBJECT(channel), "port-name");
+    g_coroutine_object_notify(G_OBJECT(channel), "port-name");
 }
 
 /* coroutine context */
@@ -275,7 +246,7 @@ static void port_handle_event(SpiceChannel *channel, SpiceMsgIn *in)
         break;
     }
 
-    emit_main_context(channel, SPICE_PORT_EVENT, event->event);
+    g_coroutine_signal_emit(channel, signals[SPICE_PORT_EVENT], 0, event->event);
 }
 
 /* coroutine context */
@@ -288,7 +259,7 @@ static void port_handle_msg(SpiceChannel *channel, SpiceMsgIn *in)
     buf = spice_msg_in_raw(in, &size);
     CHANNEL_DEBUG(channel, "port %p got %d %p", channel, size, buf);
     port_set_opened(self, true);
-    emit_main_context(channel, SPICE_PORT_DATA, buf, size);
+    g_coroutine_signal_emit(channel, signals[SPICE_PORT_DATA], 0, buf, size);
 }
 
 /**
diff --git a/gtk/channel-record.c b/gtk/channel-record.c
index d4f47ba..20af3de 100644
--- a/gtk/channel-record.c
+++ b/gtk/channel-record.c
@@ -251,36 +251,6 @@ static void spice_record_channel_class_init(SpiceRecordChannelClass *klass)
     channel_set_handlers(SPICE_CHANNEL_CLASS(klass));
 }
 
-/* signal trampoline---------------------------------------------------------- */
-
-struct SPICE_RECORD_START {
-    gint format;
-    gint channels;
-    gint frequency;
-};
-
-struct SPICE_RECORD_STOP {
-};
-
-/* main context */
-static void do_emit_main_context(GObject *object, int signum, gpointer params)
-{
-    switch (signum) {
-    case SPICE_RECORD_START: {
-        struct SPICE_RECORD_START *p = params;
-        g_signal_emit(object, signals[signum], 0,
-                      p->format, p->channels, p->frequency);
-        break;
-    }
-    case SPICE_RECORD_STOP: {
-        g_signal_emit(object, signals[signum], 0);
-        break;
-    }
-    default:
-        g_warn_if_reached();
-    }
-}
-
 /* main context */
 static void spice_record_mode(SpiceRecordChannel *channel, uint32_t time,
                               uint32_t mode, uint8_t *data, uint32_t data_size)
@@ -451,8 +421,8 @@ static void record_handle_start(SpiceChannel *channel, SpiceMsgIn *in)
     c->last_frame = g_malloc(c->frame_bytes);
     c->last_frame_current = 0;
 
-    emit_main_context(channel, SPICE_RECORD_START,
-                      start->format, start->channels, start->frequency);
+    g_coroutine_signal_emit(channel, signals[SPICE_RECORD_START], 0,
+                            start->format, start->channels, start->frequency);
 }
 
 /* coroutine context */
@@ -460,7 +430,7 @@ static void record_handle_stop(SpiceChannel *channel, SpiceMsgIn *in)
 {
     SpiceRecordChannelPrivate *rc = SPICE_RECORD_CHANNEL(channel)->priv;
 
-    emit_main_context(channel, SPICE_RECORD_STOP);
+    g_coroutine_signal_emit(channel, signals[SPICE_RECORD_STOP], 0);
     rc->started = FALSE;
 }
 
@@ -479,7 +449,7 @@ static void record_handle_set_volume(SpiceChannel *channel, SpiceMsgIn *in)
     c->nchannels = vol->nchannels;
     c->volume = g_new(guint16, c->nchannels);
     memcpy(c->volume, vol->volume, sizeof(guint16) * c->nchannels);
-    g_object_notify_main_context(G_OBJECT(channel), "volume");
+    g_coroutine_object_notify(G_OBJECT(channel), "volume");
 }
 
 /* coroutine context */
@@ -489,7 +459,7 @@ static void record_handle_set_mute(SpiceChannel *channel, SpiceMsgIn *in)
     SpiceMsgAudioMute *m = spice_msg_in_parsed(in);
 
     c->mute = m->mute;
-    g_object_notify_main_context(G_OBJECT(channel), "mute");
+    g_coroutine_object_notify(G_OBJECT(channel), "mute");
 }
 
 static void channel_set_handlers(SpiceChannelClass *klass)
diff --git a/gtk/gio-coroutine.c b/gtk/gio-coroutine.c
index d3ac16c..c903bd2 100644
--- a/gtk/gio-coroutine.c
+++ b/gtk/gio-coroutine.c
@@ -184,20 +184,21 @@ gboolean g_coroutine_condition_wait(GCoroutine *self, GConditionWaitFunc func, g
 
 struct signal_data
 {
-    GObject *object;
+    gpointer instance;
     struct coroutine *caller;
-    int signum;
-    gpointer params;
-    GSignalEmitMainFunc func;
-    const char *debug_info;
+    guint signal_id;
+    GQuark detail;
+    const gchar *propname;
     gboolean notified;
+    va_list var_args;
 };
 
 static gboolean emit_main_context(gpointer opaque)
 {
     struct signal_data *signal = opaque;
 
-    signal->func(signal->object, signal->signum, signal->params);
+    g_signal_emit_valist(signal->instance, signal->signal_id,
+                         signal->detail, signal->var_args);
     signal->notified = TRUE;
 
     coroutine_yieldto(signal->caller, NULL);
@@ -205,41 +206,36 @@ static gboolean emit_main_context(gpointer opaque)
     return FALSE;
 }
 
-/* coroutine -> main context */
-void g_signal_emit_main_context(GObject *object,
-                                GSignalEmitMainFunc emit_main_func,
-                                int signum,
-                                gpointer params,
-                                const char *debug_info)
+void
+g_coroutine_signal_emit(gpointer instance, guint signal_id,
+                        GQuark detail, ...)
 {
-    struct signal_data data;
+    struct signal_data data = {
+        .instance = instance,
+        .signal_id = signal_id,
+        .detail = detail,
+        .caller = coroutine_self(),
+    };
 
-    g_return_if_fail(coroutine_self()->caller);
-
-    data.object = object;
-    data.caller = coroutine_self();
-    data.signum = signum;
-    data.params = params;
-    data.func = emit_main_func;
-    data.debug_info = debug_info;
-    data.notified = FALSE;
-    g_idle_add(emit_main_context, &data);
-
-    /* This switches to the system coroutine context, lets
-     * the idle function run to dispatch the signal, and
-     * finally returns once complete. ie this is synchronous
-     * from the POV of the coroutine despite there being
-     * an idle function involved
-     */
-    coroutine_yield(NULL);
-    g_warn_if_fail(data.notified);
+    va_start (data.var_args, detail);
+
+    if (coroutine_self_is_main()) {
+        g_signal_emit_valist(instance, signal_id, detail, data.var_args);
+    } else {
+        g_idle_add(emit_main_context, &data);
+        coroutine_yield(NULL);
+        g_warn_if_fail(data.notified);
+    }
+
+    va_end (data.var_args);
 }
 
+
 static gboolean notify_main_context(gpointer opaque)
 {
     struct signal_data *signal = opaque;
 
-    g_object_notify(signal->object, signal->params);
+    g_object_notify(signal->instance, signal->propname);
     signal->notified = TRUE;
 
     coroutine_yieldto(signal->caller, NULL);
@@ -248,8 +244,8 @@ static gboolean notify_main_context(gpointer opaque)
 }
 
 /* coroutine -> main context */
-void g_object_notify_main_context(GObject *object,
-                                  const gchar *property_name)
+void g_coroutine_object_notify(GObject *object,
+                               const gchar *property_name)
 {
     struct signal_data data;
 
@@ -257,9 +253,9 @@ void g_object_notify_main_context(GObject *object,
         g_object_notify(object, property_name);
     } else {
 
-        data.object = object;
+        data.instance = object;
         data.caller = coroutine_self();
-        data.params = (gpointer)property_name;
+        data.propname = (gpointer)property_name;
         data.notified = FALSE;
 
         g_idle_add(notify_main_context, &data);
diff --git a/gtk/gio-coroutine.h b/gtk/gio-coroutine.h
index 1c4094e..b3a6d78 100644
--- a/gtk/gio-coroutine.h
+++ b/gtk/gio-coroutine.h
@@ -56,9 +56,10 @@ gboolean     g_coroutine_condition_wait (GCoroutine *coroutine,
                                          GConditionWaitFunc func, gpointer data);
 void         g_coroutine_condition_cancel(GCoroutine *coroutine);
 
-void         g_signal_emit_main_context(GObject *object, GSignalEmitMainFunc func,
-                                        int signum, gpointer params, const char *debug_info);
-void         g_object_notify_main_context(GObject *object, const gchar *property_name);
+void         g_coroutine_signal_emit (gpointer instance, guint signal_id,
+                                      GQuark detail, ...);
+
+void         g_coroutine_object_notify(GObject *object, const gchar *property_name);
 
 G_END_DECLS
 
diff --git a/gtk/spice-channel-priv.h b/gtk/spice-channel-priv.h
index 607c0d4..03eed38 100644
--- a/gtk/spice-channel-priv.h
+++ b/gtk/spice-channel-priv.h
@@ -186,17 +186,6 @@ void spice_caps_set(GArray *caps, guint32 cap, const gchar *desc);
 #define spice_channel_set_capability(channel, cap)                      \
     spice_caps_set(SPICE_CHANNEL(channel)->priv->caps, cap, #cap)
 
-/* coroutine context */
-#define emit_main_context(object, event, args...)                                      \
-    G_STMT_START {                                                                     \
-        if (coroutine_self_is_main()) {                                 \
-            do_emit_main_context(G_OBJECT(object), event, &((struct event) { args })); \
-        } else {                                                                       \
-            g_signal_emit_main_context(G_OBJECT(object), do_emit_main_context,         \
-                                       event, &((struct event) { args }), G_STRLOC);   \
-        }                                                                              \
-    } G_STMT_END
-
 gchar *spice_channel_supported_string(void);
 
 void spice_vmc_write_async(SpiceChannel *self,
diff --git a/gtk/spice-channel.c b/gtk/spice-channel.c
index e460590..1a4a5bf 100644
--- a/gtk/spice-channel.c
+++ b/gtk/spice-channel.c
@@ -734,29 +734,6 @@ void spice_msg_out_send_internal(SpiceMsgOut *out)
     spice_channel_write_msg(out->channel, out);
 }
 
-/* ---------------------------------------------------------------- */
-
-struct SPICE_CHANNEL_EVENT {
-    SpiceChannelEvent event;
-};
-
-/* main context */
-static void do_emit_main_context(GObject *object, int signum, gpointer params)
-{
-    switch (signum) {
-    case SPICE_CHANNEL_EVENT: {
-        struct SPICE_CHANNEL_EVENT *p = params;
-        g_signal_emit(object, signals[signum], 0, p->event);
-        break;
-    }
-    case SPICE_CHANNEL_OPEN_FD:
-        g_warning("this signal is only sent directly from main context");
-        break;
-    default:
-        g_warn_if_reached();
-    }
-}
-
 /*
  * Write all 'data' of length 'datalen' bytes out to
  * the wire
@@ -1094,19 +1071,19 @@ static void spice_channel_recv_auth(SpiceChannel *channel)
     if (rc != sizeof(link_res)) {
         CHANNEL_DEBUG(channel, "incomplete auth reply (%d/%" G_GSIZE_FORMAT ")",
                     rc, sizeof(link_res));
-        emit_main_context(channel, SPICE_CHANNEL_EVENT, SPICE_CHANNEL_ERROR_LINK);
+        g_coroutine_signal_emit(channel, signals[SPICE_CHANNEL_EVENT], 0, SPICE_CHANNEL_ERROR_LINK);
         return;
     }
 
     if (link_res != SPICE_LINK_ERR_OK) {
         CHANNEL_DEBUG(channel, "link result: reply %d", link_res);
-        emit_main_context(channel, SPICE_CHANNEL_EVENT, SPICE_CHANNEL_ERROR_AUTH);
+        g_coroutine_signal_emit(channel, signals[SPICE_CHANNEL_EVENT], 0, SPICE_CHANNEL_ERROR_AUTH);
         return;
     }
 
     c->state = SPICE_CHANNEL_STATE_READY;
 
-    emit_main_context(channel, SPICE_CHANNEL_EVENT, SPICE_CHANNEL_OPENED);
+    g_coroutine_signal_emit(channel, signals[SPICE_CHANNEL_EVENT], 0, SPICE_CHANNEL_OPENED);
 
     if (c->state == SPICE_CHANNEL_STATE_MIGRATION_HANDSHAKE) {
         spice_channel_send_migration_handshake(channel);
@@ -1233,7 +1210,7 @@ error:
         return FALSE;
     }
 
-    emit_main_context(channel, SPICE_CHANNEL_EVENT, SPICE_CHANNEL_ERROR_LINK);
+    g_coroutine_signal_emit(channel, signals[SPICE_CHANNEL_EVENT], 0, SPICE_CHANNEL_ERROR_LINK);
     return FALSE;
 }
 
@@ -1648,7 +1625,7 @@ complete:
     CHANNEL_DEBUG(channel, "%s", "SASL authentication complete");
     spice_channel_read(channel, &len, sizeof(len));
     if (len != SPICE_LINK_ERR_OK)
-        emit_main_context(channel, SPICE_CHANNEL_EVENT, SPICE_CHANNEL_ERROR_AUTH);
+        g_coroutine_signal_emit(channel, signals[SPICE_CHANNEL_EVENT], 0, SPICE_CHANNEL_ERROR_AUTH);
     ret = len == SPICE_LINK_ERR_OK;
     /* This must come *after* check-auth-result, because the former
      * is defined to be sent unencrypted, and setting saslconn turns
@@ -1659,7 +1636,7 @@ complete:
 error:
     if (saslconn)
         sasl_dispose(&saslconn);
-    emit_main_context(channel, SPICE_CHANNEL_EVENT, SPICE_CHANNEL_ERROR_AUTH);
+    g_coroutine_signal_emit(channel, signals[SPICE_CHANNEL_EVENT], 0, SPICE_CHANNEL_ERROR_AUTH);
     c->has_error = TRUE; /* force disconnect */
     ret = FALSE;
 
@@ -1691,7 +1668,7 @@ static void spice_channel_recv_link_msg(SpiceChannel *channel, gboolean *switch_
     if (c->peer_pos != c->peer_hdr.size) {
         g_critical("%s: %s: incomplete link reply (%d/%d)",
                   c->name, __FUNCTION__, rc, c->peer_hdr.size);
-        emit_main_context(channel, SPICE_CHANNEL_EVENT, SPICE_CHANNEL_ERROR_LINK);
+        g_coroutine_signal_emit(channel, signals[SPICE_CHANNEL_EVENT], 0, SPICE_CHANNEL_ERROR_LINK);
         return;
     }
     switch (c->peer_msg->error) {
@@ -1759,7 +1736,7 @@ static void spice_channel_recv_link_msg(SpiceChannel *channel, gboolean *switch_
 
 error:
     SPICE_CHANNEL_GET_CLASS(channel)->channel_disconnect(channel);
-    emit_main_context(channel, SPICE_CHANNEL_EVENT, SPICE_CHANNEL_ERROR_LINK);
+    g_coroutine_signal_emit(channel, signals[SPICE_CHANNEL_EVENT], 0, SPICE_CHANNEL_ERROR_LINK);
 }
 
 /* system context */
@@ -2142,9 +2119,9 @@ static gboolean spice_channel_iterate(SpiceChannel *channel)
     if (c->has_error) {
         CHANNEL_DEBUG(channel, "channel got error");
         if (c->state > SPICE_CHANNEL_STATE_CONNECTING)
-            emit_main_context(channel, SPICE_CHANNEL_EVENT,
-                              c->state == SPICE_CHANNEL_STATE_READY ?
-                              SPICE_CHANNEL_ERROR_IO : SPICE_CHANNEL_ERROR_LINK);
+            g_coroutine_signal_emit(channel, signals[SPICE_CHANNEL_EVENT], 0,
+                                    c->state == SPICE_CHANNEL_STATE_READY ?
+                                    SPICE_CHANNEL_ERROR_IO : SPICE_CHANNEL_ERROR_LINK);
         return FALSE;
     }
 
@@ -2272,13 +2249,13 @@ static void *spice_channel_coroutine(void *data)
     if (spice_session_get_client_provided_socket(c->session)) {
         if (c->fd < 0) {
             g_critical("fd not provided!");
-            emit_main_context(channel, SPICE_CHANNEL_EVENT, SPICE_CHANNEL_ERROR_CONNECT);
+            g_coroutine_signal_emit(channel, signals[SPICE_CHANNEL_EVENT], 0, SPICE_CHANNEL_ERROR_CONNECT);
             goto cleanup;
         }
 
         if (!(c->sock = g_socket_new_from_fd(c->fd, NULL))) {
                 CHANNEL_DEBUG(channel, "Failed to open socket from fd %d", c->fd);
-                emit_main_context(channel, SPICE_CHANNEL_EVENT, SPICE_CHANNEL_ERROR_CONNECT);
+                g_coroutine_signal_emit(channel, signals[SPICE_CHANNEL_EVENT], 0, SPICE_CHANNEL_ERROR_CONNECT);
                 goto cleanup;
         }
 
@@ -2298,7 +2275,7 @@ reconnect:
             goto reconnect;
         } else {
             CHANNEL_DEBUG(channel, "Connect error");
-            emit_main_context(channel, SPICE_CHANNEL_EVENT, SPICE_CHANNEL_ERROR_CONNECT);
+            g_coroutine_signal_emit(channel, signals[SPICE_CHANNEL_EVENT], 0, SPICE_CHANNEL_ERROR_CONNECT);
             g_clear_error(&c->error);
             goto cleanup;
         }
@@ -2311,7 +2288,7 @@ reconnect:
         c->ctx = SSL_CTX_new(SSLv23_method());
         if (c->ctx == NULL) {
             g_critical("SSL_CTX_new failed");
-            emit_main_context(channel, SPICE_CHANNEL_EVENT, SPICE_CHANNEL_ERROR_TLS);
+            g_coroutine_signal_emit(channel, signals[SPICE_CHANNEL_EVENT], 0, SPICE_CHANNEL_ERROR_TLS);
             goto cleanup;
         }
 
@@ -2327,7 +2304,7 @@ reconnect:
                     g_warning("only pubkey active");
                     verify = SPICE_SESSION_VERIFY_PUBKEY;
                 } else {
-                    emit_main_context(channel, SPICE_CHANNEL_EVENT, SPICE_CHANNEL_ERROR_TLS);
+                    g_coroutine_signal_emit(channel, signals[SPICE_CHANNEL_EVENT], 0, SPICE_CHANNEL_ERROR_TLS);
                     goto cleanup;
                 }
             }
@@ -2345,7 +2322,7 @@ reconnect:
         c->ssl = SSL_new(c->ctx);
         if (c->ssl == NULL) {
             g_critical("SSL_new failed");
-            emit_main_context(channel, SPICE_CHANNEL_EVENT, SPICE_CHANNEL_ERROR_TLS);
+            g_coroutine_signal_emit(channel, signals[SPICE_CHANNEL_EVENT], 0, SPICE_CHANNEL_ERROR_TLS);
             goto cleanup;
         }
 
@@ -2378,7 +2355,7 @@ ssl_reconnect:
             } else {
                 g_warning("%s: SSL_connect: %s",
                           c->name, ERR_error_string(rc, NULL));
-                emit_main_context(channel, SPICE_CHANNEL_EVENT, SPICE_CHANNEL_ERROR_TLS);
+                g_coroutine_signal_emit(channel, signals[SPICE_CHANNEL_EVENT], 0, SPICE_CHANNEL_ERROR_TLS);
                 goto cleanup;
             }
         }
@@ -2611,7 +2588,7 @@ static void channel_disconnect(SpiceChannel *channel)
     c->has_error = TRUE; /* break the loop */
 
     if (c->state == SPICE_CHANNEL_STATE_READY)
-        emit_main_context(channel, SPICE_CHANNEL_EVENT, SPICE_CHANNEL_CLOSED);
+        g_coroutine_signal_emit(channel, signals[SPICE_CHANNEL_EVENT], 0, SPICE_CHANNEL_CLOSED);
 
     c->state = SPICE_CHANNEL_STATE_UNCONNECTED;
     spice_channel_reset(channel, FALSE);
diff --git a/gtk/spice-session.c b/gtk/spice-session.c
index c168bc3..fed57a4 100644
--- a/gtk/spice-session.c
+++ b/gtk/spice-session.c
@@ -124,21 +124,6 @@ enum {
 
 static guint signals[SPICE_SESSION_LAST_SIGNAL];
 
-struct SPICE_SESSION_MM_TIME_RESET {
-};
-
-/* main context */
-static void do_emit_main_context(GObject *object, int signum, gpointer params)
-{
-    switch (signum) {
-    case SPICE_SESSION_MM_TIME_RESET:
-        g_signal_emit(object, signals[signum], 0);
-        break;
-    default:
-        g_warn_if_reached();
-    }
-}
-
 static void update_proxy(SpiceSession *self, const gchar *str)
 {
     SpiceSessionPrivate *s = self->priv;
@@ -616,7 +601,7 @@ static void spice_session_set_property(GObject      *gobject,
         break;
     case PROP_READ_ONLY:
         s->read_only = g_value_get_boolean(value);
-        g_object_notify_main_context(gobject, "read-only");
+        g_coroutine_object_notify(gobject, "read-only");
         break;
     case PROP_CACHE_SIZE:
         s->images_cache_size = g_value_get_int(value);
@@ -2006,7 +1991,7 @@ void spice_session_set_mm_time(SpiceSession *session, guint32 time)
     if (time > old_time + MM_TIME_DIFF_RESET_THRESH ||
         time < old_time) {
         SPICE_DEBUG("%s: mm-time-reset, old %u, new %u", __FUNCTION__, old_time, s->mm_time);
-        emit_main_context(session, SPICE_SESSION_MM_TIME_RESET);
+        g_coroutine_signal_emit(session, signals[SPICE_SESSION_MM_TIME_RESET], 0);
     }
 }
 
@@ -2066,7 +2051,7 @@ void spice_session_set_migration_state(SpiceSession *session, SpiceSessionMigrat
 
     g_return_if_fail(s != NULL);
     s->migration_state = state;
-    g_object_notify_main_context(G_OBJECT(session), "migration-state");
+    g_coroutine_object_notify(G_OBJECT(session), "migration-state");
 }
 
 G_GNUC_INTERNAL
@@ -2161,7 +2146,7 @@ void spice_session_set_uuid(SpiceSession *session, guint8 uuid[16])
     g_return_if_fail(s != NULL);
     memcpy(s->uuid, uuid, sizeof(s->uuid));
 
-    g_object_notify_main_context(G_OBJECT(session), "uuid");
+    g_coroutine_object_notify(G_OBJECT(session), "uuid");
 }
 
 G_GNUC_INTERNAL
@@ -2173,7 +2158,7 @@ void spice_session_set_name(SpiceSession *session, const gchar *name)
     g_free(s->name);
     s->name = g_strdup(name);
 
-    g_object_notify_main_context(G_OBJECT(session), "name");
+    g_coroutine_object_notify(G_OBJECT(session), "name");
 }
 
 G_GNUC_INTERNAL
commit 47b831d64a3ab11e5e2c2994e509ae1f813147f9
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Thu May 29 22:56:09 2014 +0200

    usbredir: don't use emit_main_context() for non-signal code
    
    The following patch deprecates the signal helper code

diff --git a/gtk/channel-usbredir.c b/gtk/channel-usbredir.c
index 239fe12..a52476a 100644
--- a/gtk/channel-usbredir.c
+++ b/gtk/channel-usbredir.c
@@ -577,38 +577,31 @@ static void usbredir_free_lock(void *user_data) {
 
 /* --------------------------------------------------------------------- */
 
-/* Events to be handled in main context */
-enum {
-    DEVICE_ERROR,
-};
-
-struct DEVICE_ERROR {
+typedef struct device_error_data {
+    SpiceUsbredirChannel *channel;
     SpiceUsbDevice *spice_device;
     GError *error;
-};
+    struct coroutine *caller;
+} device_error_data;
 
 /* main context */
-static void do_emit_main_context(GObject *object, int event, gpointer params)
+static gboolean device_error(gpointer user_data)
 {
-    SpiceUsbredirChannel *channel = SPICE_USBREDIR_CHANNEL(object);
+    device_error_data *data = user_data;
+    SpiceUsbredirChannel *channel = data->channel;
     SpiceUsbredirChannelPrivate *priv = channel->priv;
 
-    switch (event) {
-    case DEVICE_ERROR: {
-        struct DEVICE_ERROR *p = params;
-        /* Check that the device has not changed before we manage to run */
-        if (p->spice_device == priv->spice_device) {
-            spice_usbredir_channel_disconnect_device(channel);
-            spice_usb_device_manager_device_error(
+    /* Check that the device has not changed before we manage to run */
+    if (data->spice_device == priv->spice_device) {
+        spice_usbredir_channel_disconnect_device(channel);
+        spice_usb_device_manager_device_error(
                 spice_usb_device_manager_get(
                     spice_channel_get_session(SPICE_CHANNEL(channel)), NULL),
-                p->spice_device, p->error);
-        }
-        break;
-    }
-    default:
-        g_warn_if_reached();
+                data->spice_device, data->error);
     }
+
+    coroutine_yieldto(data->caller, NULL);
+    return FALSE;
 }
 
 /* --------------------------------------------------------------------- */
@@ -626,6 +619,7 @@ static void usbredir_handle_msg(SpiceChannel *c, SpiceMsgIn *in)
 {
     SpiceUsbredirChannel *channel = SPICE_USBREDIR_CHANNEL(c);
     SpiceUsbredirChannelPrivate *priv = channel->priv;
+    device_error_data data;
     int r, size;
     uint8_t *buf;
 
@@ -670,9 +664,14 @@ static void usbredir_handle_msg(SpiceChannel *c, SpiceMsgIn *in)
 
         CHANNEL_DEBUG(c, "%s", err->message);
 
-        spice_device = g_boxed_copy(spice_usb_device_get_type(), spice_device);
-        emit_main_context(channel, DEVICE_ERROR, spice_device, err);
-        g_boxed_free(spice_usb_device_get_type(), spice_device);
+        data.channel = channel;
+        data.caller = coroutine_self();
+        data.spice_device = g_boxed_copy(spice_usb_device_get_type(), spice_device);
+        data.error = err;
+        g_idle_add(device_error, &data);
+        coroutine_yield(NULL);
+
+        g_boxed_free(spice_usb_device_get_type(), data.spice_device);
 
         g_error_free(err);
     }


More information about the Spice-commits mailing list