void
ring_text_manager_add_capabilities(RingTextManager *self,
  guint handle,
  GPtrArray *returns)
{
  RingTextManagerPrivate *priv = RING_TEXT_MANAGER(self)->priv;
  char const *id = ring_connection_inspect_contact(priv->connection, handle);
  guint selfhandle = tp_base_connection_get_self_handle(
    (TpBaseConnection *)priv->connection);
  char *destination;

  if (id == NULL)
    return;

  /* Some UIs create channels even if they do not intend to send anything */
  /* Allow them to do so */

  destination = ring_text_channel_destination(id);

  if (handle == selfhandle || modem_sms_is_valid_address (destination)) {
    g_ptr_array_add(returns,
      ring_contact_capability_new(handle,
        TP_IFACE_CHANNEL_TYPE_TEXT,
        TP_CONNECTION_CAPABILITY_FLAG_CREATE,
        RING_TEXT_CHANNEL_CAPABILITY_FLAGS));
  }

  g_free(destination);
}
void
ring_media_manager_add_capabilities(RingMediaManager *self,
  guint handle,
  GPtrArray *returns)
{
  RingMediaManagerPrivate *priv = RING_MEDIA_MANAGER(self)->priv;
  char const *id = ring_connection_inspect_contact(priv->connection, handle);
  guint selfhandle = tp_base_connection_get_self_handle(
    (TpBaseConnection *)priv->connection);

  if (id == NULL)
    return;

  if (!ring_media_manager_is_connected (self))
    return;

  /* XXX - should check if we are in emergency call mode only status */

  if (handle == selfhandle) {
    if (priv->capability_flags)
      g_ptr_array_add(returns,
        ring_contact_capability_new(handle,
          TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA,
          TP_CONNECTION_CAPABILITY_FLAG_CREATE |
          TP_CONNECTION_CAPABILITY_FLAG_INVITE,
          RING_MEDIA_CHANNEL_CAPABILITY_FLAGS));
  }
  else if (modem_call_is_valid_address (id)) {
    g_ptr_array_add(returns,
      ring_contact_capability_new(handle,
        TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA,
        TP_CONNECTION_CAPABILITY_FLAG_CREATE |
        TP_CONNECTION_CAPABILITY_FLAG_INVITE,
        RING_MEDIA_CHANNEL_CAPABILITY_FLAGS));
  }
}
static gboolean
ring_media_requestotron(RingMediaManager *self,
  gpointer request,
  GHashTable *properties,
  RequestotronMethod kind)
{
  RingMediaManagerPrivate *priv = self->priv;
  TpHandle handle;

  /* If we're not connected, calls aren't supported. */
  if (self->priv->call_service == NULL)
    return FALSE;

  handle = tp_asv_get_uint32 (properties,
      TP_IFACE_CHANNEL ".TargetHandle", NULL);

  if (kind == METHOD_COMPATIBLE &&
    handle == 0 &&
    ring_properties_satisfy(properties,
      ring_anon_channel_fixed_properties(),
      ring_anon_channel_allowed_properties)) {
    return ring_media_manager_outgoing_call(self, request, 0, 0, NULL, FALSE);
  }

  if (tp_asv_get_initial_video (properties, FALSE))
    {
      tp_channel_manager_emit_request_failed (self, request,
          TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
          "Video calls are not supported");
      return TRUE;
    }

  if (handle != 0 &&
    ring_properties_satisfy(properties,
      ring_call_channel_fixed_properties(),
      ring_call_channel_allowed_properties)) {
    RingCallChannel *channel;
    char const *target_id;
    GError *error = NULL;

    target_id = ring_connection_inspect_contact(priv->connection, handle);

    if (!modem_call_validate_address(target_id, &error)) {
      tp_channel_manager_emit_request_failed(
        self, request, TP_ERRORS, TP_ERROR_INVALID_HANDLE, error->message);
      g_error_free(error);
      return TRUE;
    }
    /* We do not yet support 'w' */
    else if (strchr(target_id, 'w')) {
      tp_channel_manager_emit_request_failed(
        self, request,
        TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
        "Dial strings containing 'w' are not supported");
      return TRUE;
    }

    if (kind == METHOD_ENSURE) {
      channel = ring_media_manager_lookup_by_peer(self, handle);
      if (channel) {
        tp_channel_manager_emit_request_already_satisfied(
          self, request, TP_EXPORTABLE_CHANNEL(channel));
        return TRUE;
      }
    }

    return ring_media_manager_outgoing_call(self, request,
      handle,
      kind == METHOD_COMPATIBLE ? handle : 0,
      modem_call_get_emergency_service(priv->call_service, target_id),
      tp_asv_get_initial_audio(properties, FALSE));
  }

  return FALSE;
}
static RingTextChannel *
ring_text_manager_request(RingTextManager *self,
  gpointer request,
  TpHandle initiator,
  TpHandle handle,
  gboolean require_mine,
  gboolean class0)
{
  RingTextManagerPrivate *priv = self->priv;
  RingTextChannel *channel;
  char *object_path;

  object_path = g_strdup_printf("%s/%s%u",
                priv->connection->parent.object_path,
                class0 ? "flash" : "text",
                (unsigned)handle);

  channel = ring_text_manager_lookup(self, object_path);

  if (channel) {
    g_free(object_path);

    if (require_mine) {
      char *message;
      channel = NULL;
      message = g_strdup_printf("Cannot create: "
                "channel with target '%s' already exists",
                ring_connection_inspect_contact(priv->connection, handle));
      DEBUG("%s", message);
      if (request)
        tp_channel_manager_emit_request_failed(self,
          request, TP_ERROR, TP_ERROR_NOT_AVAILABLE, message);
      g_assert(request);
      g_free(message);
      return NULL;
    }
    else {
      if (request)
        tp_channel_manager_emit_request_already_satisfied(
          self, request, TP_EXPORTABLE_CHANNEL(channel));
      return channel;
    }
  }

  channel = g_object_new (RING_TYPE_TEXT_CHANNEL,
      "connection", self->priv->connection,
      "object-path", object_path,
      "handle-type", TP_HANDLE_TYPE_CONTACT,
      "handle", handle,
      "initiator-handle", initiator,
      "requested", request != NULL,
      "sms-flash", class0,
      NULL);
  g_free(object_path);

  g_object_get(channel, "object_path", &object_path, NULL);

  g_hash_table_insert(priv->channels, object_path, channel);

  g_signal_connect(channel, "closed", (GCallback)on_text_channel_closed, self);

  GSList *requests = request ? g_slist_prepend(NULL, request) : NULL;

  tp_channel_manager_emit_new_channel(
    self, TP_EXPORTABLE_CHANNEL(channel), requests);

  DEBUG("New channel emitted");

  g_slist_free(requests);

  return channel;
}