Example #1
0
static gboolean
add_member (GObject *object,
            TpHandle member,
            const gchar *message,
            GError **error)
{
  ExampleCallableMediaChannel *self = EXAMPLE_CALLABLE_MEDIA_CHANNEL (object);
  TpHandleRepoIface *contact_repo = tp_base_connection_get_handles
      (self->priv->conn, TP_HANDLE_TYPE_CONTACT);

  /* In connection managers that supported the RequestChannel method for
   * streamed media channels, it would be necessary to support adding the
   * called contact to the members of an outgoing call. However, in this
   * legacy-free example, we don't support that usage, so the only use for
   * AddMembers is to accept an incoming call.
   */

  if (member == self->group.self_handle &&
      tp_handle_set_is_member (self->group.local_pending, member))
    {
      /* We're in local-pending, move to members to accept. */
      TpIntSet *set = tp_intset_new_containing (member);
      GHashTableIter iter;
      gpointer v;

      g_assert (self->priv->progress == PROGRESS_CALLING);

      g_message ("SIGNALLING: send: Accepting incoming call from %s",
          tp_handle_inspect (contact_repo, self->priv->handle));

      self->priv->progress = PROGRESS_ACTIVE;

      tp_group_mixin_change_members (object, "",
          set /* added */,
          NULL /* nobody removed */,
          NULL /* nobody added to local pending */,
          NULL /* nobody added to remote pending */,
          member /* actor */, TP_CHANNEL_GROUP_CHANGE_REASON_NONE);

      tp_intset_destroy (set);

      g_hash_table_iter_init (&iter, self->priv->streams);

      while (g_hash_table_iter_next (&iter, NULL, &v))
        {
          /* we accept the proposed stream direction... */
          example_callable_media_stream_accept_proposed_direction (v);
          /* ... and the stream tries to connect */
          example_callable_media_stream_connect (v);
        }

      return TRUE;
    }

  /* Otherwise it's a meaningless request, so reject it. */
  g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
      "Cannot add handle %u to channel", member);
  return FALSE;
}
Example #2
0
static void
example_callable_media_channel_close (ExampleCallableMediaChannel *self,
                                      TpHandle actor,
                                      TpChannelGroupChangeReason reason)
{
  if (self->priv->progress != PROGRESS_ENDED)
    {
      TpIntSet *everyone;

      self->priv->progress = PROGRESS_ENDED;

      if (actor == self->group.self_handle)
        {
          const gchar *send_reason;

          /* In a real protocol these would be some sort of real protocol
           * construct, like an XMPP error stanza or a SIP error code */
          switch (reason)
            {
            case TP_CHANNEL_GROUP_CHANGE_REASON_BUSY:
              send_reason = "<user-is-busy/>";
              break;

            case TP_CHANNEL_GROUP_CHANGE_REASON_NO_ANSWER:
              send_reason = "<no-answer/>";
              break;

            default:
              send_reason = "<call-terminated/>";
            }

          g_message ("SIGNALLING: send: Terminating call: %s", send_reason);
        }

      everyone = tp_intset_new_containing (self->priv->handle);
      tp_intset_add (everyone, self->group.self_handle);
      tp_group_mixin_change_members ((GObject *) self, "",
          NULL /* nobody added */,
          everyone /* removed */,
          NULL /* nobody locally pending */,
          NULL /* nobody remotely pending */,
          actor,
          reason);
      tp_intset_destroy (everyone);

      g_signal_emit (self, signals[SIGNAL_CALL_TERMINATED], 0);
      tp_svc_channel_emit_closed (self);
    }
}
static gboolean
add_member (GObject *obj,
            TpHandle handle,
            const gchar *message,
            GError **error)
{
  TpTestsTextChannelGroup *self = TP_TESTS_TEXT_CHANNEL_GROUP (obj);
  TpIntSet *add = tp_intset_new ();

  tp_intset_add (add, handle);
  tp_group_mixin_change_members (obj, message, add, NULL, NULL, NULL,
      self->conn->self_handle, TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
  tp_intset_destroy (add);

  return TRUE;
}
Example #4
0
static void
constructed (GObject *object)
{
  void (*chain_up) (GObject *) =
      ((GObjectClass *) example_callable_media_channel_parent_class)->constructed;
  ExampleCallableMediaChannel *self = EXAMPLE_CALLABLE_MEDIA_CHANNEL (object);
  TpHandleRepoIface *contact_repo = tp_base_connection_get_handles
      (self->priv->conn, TP_HANDLE_TYPE_CONTACT);
  TpIntSet *members;
  TpIntSet *local_pending;

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

  tp_handle_ref (contact_repo, self->priv->handle);
  tp_handle_ref (contact_repo, self->priv->initiator);

  tp_dbus_daemon_register_object (
      tp_base_connection_get_dbus_daemon (self->priv->conn),
      self->priv->object_path, self);

  tp_group_mixin_init (object,
      G_STRUCT_OFFSET (ExampleCallableMediaChannel, group),
      contact_repo, self->priv->conn->self_handle);

  /* Initially, the channel contains the initiator as a member; they are also
   * the actor for the change that adds any initial members. */

  members = tp_intset_new_containing (self->priv->initiator);

  if (self->priv->locally_requested)
    {
      /* Nobody is locally pending. The remote peer will turn up in
       * remote-pending state when we actually contact them, which is done
       * in RequestStreams */
      self->priv->progress = PROGRESS_NONE;
      local_pending = NULL;
    }
  else
    {
      /* This is an incoming call, so the self-handle is locally
       * pending, to indicate that we need to answer. */
      self->priv->progress = PROGRESS_CALLING;
      local_pending = tp_intset_new_containing (self->priv->conn->self_handle);
    }

  tp_group_mixin_change_members (object, "",
      members /* added */,
      NULL /* nobody removed */,
      local_pending, /* added to local-pending */
      NULL /* nobody added to remote-pending */,
      self->priv->initiator /* actor */, TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
  tp_intset_destroy (members);

  if (local_pending != NULL)
    tp_intset_destroy (local_pending);

  /* We don't need to allow adding or removing members to this Group in ways
   * that need flags set, so the only flag we set is to say we support the
   * Properties interface to the Group.
   *
   * It doesn't make sense to add anyone to the Group, since we already know
   * who we're going to call (or were called by). The only call to AddMembers
   * we need to support is to move ourselves from local-pending to member in
   * the incoming call case, and that's always allowed anyway.
   *
   * (Connection managers that support the various backwards-compatible
   * ways to make an outgoing StreamedMedia channel have to support adding the
   * peer to remote-pending, but that has no actual effect other than to
   * obscure what's going on; in this one, there's no need to support that
   * usage.)
   *
   * Similarly, it doesn't make sense to remove anyone from this Group apart
   * from ourselves (to hang up), and removing the SelfHandle is always
   * allowed anyway.
   */
  tp_group_mixin_change_flags (object, TP_CHANNEL_GROUP_FLAG_PROPERTIES, 0);

  /* Future versions of telepathy-spec will allow a channel request to
   * say "initially include an audio stream" and/or "initially include a video
   * stream", which would be represented like this; we don't support this
   * usage yet, though, so ExampleCallableMediaManager will never invoke
   * our constructor in this way. */
  g_assert (!(self->priv->locally_requested && self->priv->initial_audio));
  g_assert (!(self->priv->locally_requested && self->priv->initial_video));

  if (!self->priv->locally_requested)
    {
      /* the caller has almost certainly asked us for some streams - there's
       * not much point in having a call otherwise */

      if (self->priv->initial_audio)
        {
          g_message ("Channel initially has an audio stream");
          example_callable_media_channel_add_stream (self,
              TP_MEDIA_STREAM_TYPE_AUDIO, FALSE);
        }

      if (self->priv->initial_video)
        {
          g_message ("Channel initially has a video stream");
          example_callable_media_channel_add_stream (self,
              TP_MEDIA_STREAM_TYPE_VIDEO, FALSE);
        }
    }
}