#include <telepathy-glib/proxy-subclass.h>
#include <telepathy-glib/dbus.h>
#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/util.h>
#include "empathy-tp-call.h"
#include "empathy-tp-contact-factory.h"
typedef struct
{
gboolean dispose_has_run;
+ TpAccount *account;
TpChannel *channel;
EmpathyContact *contact;
gboolean is_incoming;
enum
{
PROP_0,
+ PROP_ACCOUNT,
PROP_CHANNEL,
PROP_CONTACT,
- PROP_IS_INCOMING,
PROP_STATUS,
PROP_AUDIO_STREAM,
PROP_VIDEO_STREAM
}
static void
-tp_call_got_contact_cb (EmpathyTpContactFactory *factory,
+tp_call_got_contact_cb (TpConnection *connection,
EmpathyContact *contact,
const GError *error,
gpointer user_data,
}
priv->contact = g_object_ref (contact);
- priv->is_incoming = TRUE;
- priv->status = EMPATHY_TP_CALL_STATUS_PENDING;
- g_object_notify (G_OBJECT (call), "is-incoming");
+
+ if (priv->status < EMPATHY_TP_CALL_STATUS_PENDING)
+ {
+ priv->status = EMPATHY_TP_CALL_STATUS_PENDING;
+ g_object_notify (G_OBJECT (call), "status");
+ }
+
g_object_notify (G_OBJECT (call), "contact");
- g_object_notify (G_OBJECT (call), "status");
}
static void
tp_intset_iter_init (&iter, set);
while (tp_intset_iter_next (&iter))
{
- if (priv->contact == NULL && iter.element != self_handle)
- {
- EmpathyTpContactFactory *factory;
- TpConnection *connection;
-
- /* We found the remote contact */
- connection = tp_channel_borrow_connection (priv->channel);
- factory = empathy_tp_contact_factory_dup_singleton (connection);
- empathy_tp_contact_factory_get_from_handle (factory, iter.element,
- tp_call_got_contact_cb, NULL, NULL, G_OBJECT (call));
- g_object_unref (factory);
- }
-
if (priv->status == EMPATHY_TP_CALL_STATUS_PENDING &&
((priv->is_incoming && iter.element == self_handle) ||
(!priv->is_incoming && iter.element != self_handle)))
g_object_unref (call);
}
-void
-empathy_tp_call_to (EmpathyTpCall *call, EmpathyContact *contact,
- gboolean audio, gboolean video)
-{
- EmpathyTpCallPriv *priv = GET_PRIV (call);
- EmpathyCapabilities capabilities = 0;
-
- g_assert (audio || video);
-
- priv->contact = g_object_ref (contact);
- priv->is_incoming = FALSE;
- priv->status = EMPATHY_TP_CALL_STATUS_PENDING;
- g_object_notify (G_OBJECT (call), "is-incoming");
- g_object_notify (G_OBJECT (call), "contact");
- g_object_notify (G_OBJECT (call), "status");
-
- if (video)
- capabilities |= EMPATHY_CAPABILITIES_VIDEO;
- if (audio)
- capabilities |= EMPATHY_CAPABILITIES_AUDIO;
-
- tp_call_request_streams_for_capabilities (call, capabilities);
-}
-
static void
tp_call_channel_invalidated_cb (TpChannel *channel,
GQuark domain,
tp_cli_channel_type_streamed_media_call_list_streams (priv->channel, -1,
tp_call_request_streams_cb, NULL, NULL, G_OBJECT (call));
+ /* Is the call incoming? */
+ priv->is_incoming = !tp_channel_get_requested (priv->channel);
+
+ /* Get the remote contact */
+ empathy_tp_contact_factory_get_from_handle (
+ tp_channel_borrow_connection (priv->channel),
+ tp_channel_get_handle (priv->channel, NULL), tp_call_got_contact_cb,
+ NULL, NULL, object);
+
/* Update status when members changes */
tp_call_update_status (call);
- g_signal_connect_swapped (priv->channel, "group-members-changed",
- G_CALLBACK (tp_call_update_status), call);
+ tp_g_signal_connect_object (priv->channel, "group-members-changed",
+ G_CALLBACK (tp_call_update_status), call, G_CONNECT_SWAPPED);
return object;
}
if (priv->contact != NULL)
g_object_unref (priv->contact);
+ tp_clear_object (&priv->account);
+
if (G_OBJECT_CLASS (empathy_tp_call_parent_class)->dispose)
G_OBJECT_CLASS (empathy_tp_call_parent_class)->dispose (object);
}
switch (prop_id)
{
+ case PROP_ACCOUNT:
+ priv->account = g_value_dup_object (value);
+ break;
case PROP_CHANNEL:
priv->channel = g_value_dup_object (value);
break;
switch (prop_id)
{
+ case PROP_ACCOUNT:
+ g_value_set_object (value, priv->channel);
+ break;
case PROP_CHANNEL:
g_value_set_object (value, priv->channel);
break;
case PROP_CONTACT:
g_value_set_object (value, priv->contact);
break;
- case PROP_IS_INCOMING:
- g_value_set_boolean (value, priv->is_incoming);
- break;
case PROP_STATUS:
g_value_set_uint (value, priv->status);
break;
g_type_class_add_private (klass, sizeof (EmpathyTpCallPriv));
+ g_object_class_install_property (object_class, PROP_ACCOUNT,
+ g_param_spec_object ("account", "TpAccount", "TpAccount",
+ TP_TYPE_ACCOUNT,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
g_object_class_install_property (object_class, PROP_CHANNEL,
g_param_spec_object ("channel", "channel", "channel",
TP_TYPE_CHANNEL,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE |
G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
+
g_object_class_install_property (object_class, PROP_CONTACT,
g_param_spec_object ("contact", "Call contact", "Call contact",
EMPATHY_TYPE_CONTACT,
G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
- g_object_class_install_property (object_class, PROP_IS_INCOMING,
- g_param_spec_boolean ("is-incoming", "Is media stream incoming",
- "Is media stream incoming", FALSE, G_PARAM_READABLE |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
+
g_object_class_install_property (object_class, PROP_STATUS,
g_param_spec_uint ("status", "Call status",
"Call status", 0, 255, 0, G_PARAM_READABLE | G_PARAM_STATIC_NICK |
G_PARAM_STATIC_BLURB));
+
g_object_class_install_property (object_class, PROP_AUDIO_STREAM,
g_param_spec_pointer ("audio-stream", "Audio stream data",
"Audio stream data",
G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
+
g_object_class_install_property (object_class, PROP_VIDEO_STREAM,
g_param_spec_pointer ("video-stream", "Video stream data",
"Video stream data",
}
EmpathyTpCall *
-empathy_tp_call_new (TpChannel *channel)
+empathy_tp_call_new (TpAccount *account,
+ TpChannel *channel)
{
+ g_return_val_if_fail (TP_IS_ACCOUNT (account), NULL);
g_return_val_if_fail (TP_IS_CHANNEL (channel), NULL);
return g_object_new (EMPATHY_TYPE_TP_CALL,
+ "account", account,
"channel", channel,
NULL);
}
g_return_if_fail (EMPATHY_IS_TP_CALL (call));
g_return_if_fail (priv->status == EMPATHY_TP_CALL_STATUS_PENDING);
- g_return_if_fail (priv->is_incoming);
+
+ if (!priv->is_incoming)
+ return;
DEBUG ("Accepting incoming call");
empathy_tp_call_get_connection_manager (EmpathyTpCall *self)
{
EmpathyTpCallPriv *priv = GET_PRIV (self);
- TpConnection *conn;
- TpAccount *account;
- if (priv->channel == NULL)
- return NULL;
-
- conn = tp_channel_borrow_connection (priv->channel);
- if (conn == NULL)
- return NULL;
-
- account = empathy_get_account_for_connection (conn);
- if (account == NULL)
- return NULL;
-
- return tp_account_get_connection_manager (account);
+ return tp_account_get_connection_manager (priv->account);
}
gboolean
g_hash_table_unref (props);
return initial_video;
}
+
+static void
+leave_remove_members_cb (TpChannel *proxy,
+ const GError *error,
+ gpointer user_data,
+ GObject *weak_object)
+{
+ EmpathyTpCall *self = user_data;
+
+ if (error == NULL)
+ return;
+
+ DEBUG ("RemoveMembers failed (%s); closing the channel", error->message);
+ empathy_tp_call_close (self);
+}
+
+void
+empathy_tp_call_leave (EmpathyTpCall *self)
+{
+ EmpathyTpCallPriv *priv = GET_PRIV (self);
+ TpHandle self_handle;
+ GArray array = { (gchar *) &self_handle, 1 };
+
+ if (!tp_proxy_has_interface_by_id (priv->channel,
+ TP_IFACE_QUARK_CHANNEL_INTERFACE_GROUP))
+ {
+ empathy_tp_call_close (self);
+ return;
+ }
+
+ self_handle = tp_channel_group_get_self_handle (priv->channel);
+ if (self_handle == 0)
+ {
+ /* we are not member of the channel */
+ empathy_tp_call_close (self);
+ return;
+ }
+
+ tp_cli_channel_interface_group_call_remove_members (priv->channel, -1, &array,
+ "", leave_remove_members_cb, self, NULL, G_OBJECT (self));
+}
+
+EmpathyTpCallStatus
+empathy_tp_call_get_status (EmpathyTpCall *self)
+{
+ EmpathyTpCallPriv *priv = GET_PRIV (self);
+
+ return priv->status;
+}
+
+TpAccount *
+empathy_tp_call_get_account (EmpathyTpCall *self)
+{
+ EmpathyTpCallPriv *priv = GET_PRIV (self);
+
+ return priv->account;
+}