static void
on_connection_future_ensure_sidecar_returned (GObject *source_object,
    GAsyncResult *result,
    gpointer user_data)
{
  GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
  gchar *object_path;
  GError *error = NULL;

  g_return_if_fail (TP_IS_CONNECTION (source_object));

  object_path = _tp_yts_connection_future_ensure_sidecar_finish (
      TP_CONNECTION (source_object), result, NULL, &error);

  if (error != NULL)
    {
      g_simple_async_result_set_from_error (res, error);
      g_clear_error (&error);
      g_simple_async_result_complete_in_idle (res);
      g_object_unref (res);
      return;
    }

  g_async_initable_new_async (TP_TYPE_YTS_STATUS, G_PRIORITY_DEFAULT, NULL,
      on_status_new_returned, res,
      "dbus-daemon", tp_proxy_get_dbus_daemon (source_object),
      "dbus-connection", tp_proxy_get_dbus_connection (source_object),
      "bus-name", tp_proxy_get_bus_name (source_object),
      "object-path", object_path,
      NULL);

  g_free (object_path);
}
static void
on_content_added_cb (TpProxy *proxy,
    const gchar *content_path,
    gpointer user_data,
    GObject *weak_object)
{
  TpyCallChannel *self = TPY_CALL_CHANNEL (proxy);
  TpyCallContent *content;

  DEBUG ("Content added: %s", content_path);

  content = g_object_new (TPY_TYPE_CALL_CONTENT,
          "bus-name", tp_proxy_get_bus_name (self),
          "dbus-daemon", tp_proxy_get_dbus_daemon (self),
          "dbus-connection", tp_proxy_get_dbus_connection (self),
          "object-path", content_path,
          NULL);

  if (content == NULL)
    {
      g_warning ("Could not create a CallContent for path %s", content_path);
      return;
    }

  g_ptr_array_add (self->priv->contents, content);
  tp_g_signal_connect_object (content, "notify::ready",
    G_CALLBACK (on_content_ready_cb), self, 0);

  g_signal_emit (self, _signals[CONTENT_ADDED], 0, content);
}
static void
tp_channel_dispatcher_constructed (GObject *object)
{
  TpChannelDispatcher *self = TP_CHANNEL_DISPATCHER (object);
  void (*chain_up) (GObject *) =
    ((GObjectClass *) tp_channel_dispatcher_parent_class)->constructed;

  if (chain_up != NULL)
    chain_up (object);

  g_return_if_fail (tp_proxy_get_dbus_daemon (self) != NULL);
}
static void
on_call_channel_get_all_properties_cb (TpProxy *proxy,
    GHashTable *properties,
    const GError *error,
    gpointer user_data,
    GObject *weak_object)
{
  TpyCallChannel *self = TPY_CALL_CHANNEL (proxy);
  GSimpleAsyncResult *result = user_data;
  GHashTable *hash_table;
  GPtrArray *contents;
  guint i;

  if (error != NULL)
    {
      g_warning ("Could not get the channel properties: %s", error->message);
      g_simple_async_result_set_from_error (result, error);
      goto out;
    }

  self->priv->state = tp_asv_get_uint32 (properties,
      "CallState", NULL);
  self->priv->flags = tp_asv_get_uint32 (properties,
      "CallFlags", NULL);
  self->priv->initial_audio = tp_asv_get_boolean (properties,
      "InitialAudio", NULL);
  self->priv->initial_video = tp_asv_get_boolean (properties,
      "InitialVideo", NULL);

  hash_table = tp_asv_get_boxed (properties,
      "CallStateDetails", TP_HASH_TYPE_STRING_VARIANT_MAP);
  if (hash_table != NULL)
    self->priv->details = g_boxed_copy (TP_HASH_TYPE_STRING_VARIANT_MAP,
        hash_table);

  hash_table = tp_asv_get_boxed (properties,
      "CallMembers", TPY_HASH_TYPE_CALL_MEMBER_MAP);
  update_call_members (self, hash_table, NULL);

  contents = tp_asv_get_boxed (properties,
      "Contents", TP_ARRAY_TYPE_OBJECT_PATH_LIST);

  for (i = 0; i < contents->len; i++)
    {
      const gchar *content_path = g_ptr_array_index (contents, i);
      TpyCallContent *content;

      DEBUG ("Content added: %s", content_path);

      content = g_object_new (TPY_TYPE_CALL_CONTENT,
              "bus-name", tp_proxy_get_bus_name (self),
              "dbus-daemon", tp_proxy_get_dbus_daemon (self),
              "dbus-connection", tp_proxy_get_dbus_connection (self),
              "object-path", content_path,
              NULL);

      if (content == NULL)
        {
          g_warning ("Could not create a CallContent for path %s", content_path);

          g_simple_async_result_set_error (result, TP_ERRORS, TP_ERROR_CONFUSED,
              "Could not create a CallContent for path %s", content_path);
          goto out;
        }

      g_ptr_array_add (self->priv->contents, content);

      tp_g_signal_connect_object (content, "notify::ready",
        G_CALLBACK (on_content_ready_cb), self, 0);
    }

  g_signal_emit (self, _signals[MEMBERS_CHANGED], 0, self->priv->members);

  self->priv->properties_retrieved = TRUE;

  maybe_go_to_ready (self);

out:
  /* TODO; ideally we should get rid of the ready property and complete once
   * all the contents have been prepared. Or maybe that should be another
   * feature? */
  g_simple_async_result_complete (result);
}