[Spice-devel] [PATCH spice-gtk 2/2] Remove coroutine trampolines

Christophe Fergeau cfergeau at redhat.com
Tue Jun 10 07:29:33 PDT 2014


Looks nice, ACK.

Christophe

On Thu, May 29, 2014 at 11:22:02PM +0200, Marc-André Lureau wrote:
> Use va_list instead of an ugly trampoline hack
> ---
>  gtk/channel-cursor.c     |  67 ++++-----------------
>  gtk/channel-display.c    |  84 +++++---------------------
>  gtk/channel-inputs.c     |  22 +------
>  gtk/channel-main.c       | 153 ++++++++---------------------------------------
>  gtk/channel-playback.c   |  64 +++-----------------
>  gtk/channel-port.c       |  39 ++----------
>  gtk/channel-record.c     |  40 ++-----------
>  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 ++------
>  12 files changed, 133 insertions(+), 510 deletions(-)
> 
> diff --git a/gtk/channel-cursor.c b/gtk/channel-cursor.c
> index d7242a6..740b6a6 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, NULL);
>  }
>  
>  /* 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, NULL);
>      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, NULL);
>      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, NULL);
>  
>  
>      if (cursor)
> @@ -512,8 +466,9 @@ 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,
> +                            NULL);
>  }
>  
>  /* coroutine context */
> @@ -525,7 +480,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, NULL);
>  }
>  
>  /* coroutine context */
> diff --git a/gtk/channel-display.c b/gtk/channel-display.c
> index ff9f85c..b623002 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, NULL);
>  
>              g_hash_table_remove(c->surfaces, GINT_TO_POINTER(c->primary->surface_id));
>          }
> @@ -757,9 +703,10 @@ 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,
> +        g_coroutine_signal_emit(channel, signals[SPICE_DISPLAY_PRIMARY_CREATE], 0,
>                            surface->format, surface->width, surface->height,
> -                          surface->stride, surface->shmid, surface->data);
> +                          surface->stride, surface->shmid, surface->data,
> +                          NULL);
>  
>          if (!spice_channel_test_capability(channel, SPICE_DISPLAY_CAP_MONITORS_CONFIG)) {
>              g_array_set_size(c->monitors, 1);
> @@ -767,7 +714,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 +763,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, NULL);
>      }
>  
>      g_hash_table_iter_init(&iter, c->surfaces);
> @@ -834,10 +781,11 @@ 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,
> +                            NULL);
>  }
>  
>  /* ------------------------------------------------------------------ */
> @@ -868,7 +816,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 +863,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, NULL);
>  }
>  
>  /* coroutine context */
> @@ -932,7 +880,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, NULL);
>  }
>  
>  /* coroutine context */
> @@ -1753,7 +1701,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, NULL);
>      }
>  
>      g_hash_table_remove(c->surfaces, GINT_TO_POINTER(surface->surface_id));
> @@ -1800,7 +1748,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..d27640b 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, NULL);
>  }
>  
>  /* 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, NULL);
>  }
>  
>  /* coroutine context */
> diff --git a/gtk/channel-main.c b/gtk/channel-main.c
> index 58f5d31..f7b4f48 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, NULL);
>  }
>  
>  /* 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, NULL);
> +        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, NULL);
>  
>          if (caps->request)
>              agent_announce_caps(self);
> @@ -1918,42 +1809,46 @@ 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),
> +                          NULL);
>  
>         if (selection == VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD)
> -            emit_main_context(self, SPICE_MAIN_CLIPBOARD,
> -                              cb->type, cb->data, msg->size - sizeof(VDAgentClipboard));
> +           g_coroutine_signal_emit(self, signals[SPICE_MAIN_CLIPBOARD], 0,
> +                              cb->type, cb->data, msg->size - sizeof(VDAgentClipboard),
> +                              NULL);
>          break;
>      }
>      case VD_AGENT_CLIPBOARD_GRAB:
>      {
>          gboolean ret;
> -        emit_main_context(self, SPICE_MAIN_CLIPBOARD_SELECTION_GRAB, selection,
> -                          (guint8*)payload, msg->size / sizeof(uint32_t), &ret);
> +        g_coroutine_signal_emit(self, signals[SPICE_MAIN_CLIPBOARD_SELECTION_GRAB], 0, selection,
> +                          (guint8*)payload, msg->size / sizeof(uint32_t), &ret,
> +                          NULL);
>          if (selection == VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD)
> -            emit_main_context(self, SPICE_MAIN_CLIPBOARD_GRAB,
> -                              payload, msg->size / sizeof(uint32_t), &ret);
> +            g_coroutine_signal_emit(self, signals[SPICE_MAIN_CLIPBOARD_GRAB], 0,
> +                              payload, msg->size / sizeof(uint32_t), &ret,
> +                              NULL);
>          break;
>      }
>      case VD_AGENT_CLIPBOARD_REQUEST:
>      {
>          gboolean ret;
>          VDAgentClipboardRequest *req = payload;
> -        emit_main_context(self, SPICE_MAIN_CLIPBOARD_SELECTION_REQUEST, selection,
> -                          req->type, &ret);
> +        g_coroutine_signal_emit(self, signals[SPICE_MAIN_CLIPBOARD_SELECTION_REQUEST], 0, selection,
> +                          req->type, &ret, NULL);
>  
>          if (selection == VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD)
> -            emit_main_context(self, SPICE_MAIN_CLIPBOARD_REQUEST,
> -                              req->type, &ret);
> +            g_coroutine_signal_emit(self, signals[SPICE_MAIN_CLIPBOARD_REQUEST], 0,
> +                              req->type, &ret, NULL);
>          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, NULL);
>  
>          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, NULL);
>          break;
>      }
>      case VD_AGENT_REPLY:
> diff --git a/gtk/channel-playback.c b/gtk/channel-playback.c
> index 7789aa8..dc3c375 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, NULL);
>  
>      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, NULL);
>      }
>  }
>  
> @@ -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, NULL);
>  }
>  
>  /* 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, NULL);
>      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..742178d 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, NULL);
>  
> -    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, NULL);
>  }
>  
>  /* 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, NULL);
>  }
>  
>  /**
> diff --git a/gtk/channel-record.c b/gtk/channel-record.c
> index d4f47ba..bca3736 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, NULL);
>  }
>  
>  /* 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, NULL);
>      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..c9c4819 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, NULL);
>          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, NULL);
>          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, NULL);
>  
>      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, NULL);
>      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, NULL);
>      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, NULL);
>      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, NULL);
>          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, NULL);
>  }
>  
>  /* 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, NULL);
>          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, NULL);
>              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, NULL);
>                  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, NULL);
>              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, NULL);
>              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, NULL);
>                      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, NULL);
>              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, NULL);
>                  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, NULL);
>  
>      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..2346187 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, NULL);
>      }
>  }
>  
> @@ -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
> -- 
> 1.9.0
> 
> _______________________________________________
> Spice-devel mailing list
> Spice-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/spice-devel
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/spice-devel/attachments/20140610/7ce9e4e1/attachment-0001.sig>


More information about the Spice-devel mailing list