#include "empathy-tp-chat.h"
#include "empathy-tp-contact-factory.h"
-#include "empathy-contact-monitor.h"
#include "empathy-contact-list.h"
-#include "empathy-dispatcher.h"
#include "empathy-marshal.h"
#include "empathy-time.h"
#include "empathy-utils.h"
#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyTpChat)
typedef struct {
gboolean dispose_has_run;
- EmpathyTpContactFactory *factory;
- EmpathyContactMonitor *contact_monitor;
+ TpAccount *account;
+ TpConnection *connection;
EmpathyContact *user;
EmpathyContact *remote_contact;
GList *members;
enum {
PROP_0,
+ PROP_ACCOUNT,
PROP_CHANNEL,
PROP_REMOTE_CONTACT,
PROP_PASSWORD_NEEDED,
}
}
+static void
+create_conference_cb (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GError *error = NULL;
+
+ if (!tp_account_channel_request_create_channel_finish (
+ TP_ACCOUNT_CHANNEL_REQUEST (source), result, &error)) {
+ DEBUG ("Failed to create conference channel: %s", error->message);
+ g_error_free (error);
+ }
+}
+
static void
tp_chat_add (EmpathyContactList *list,
EmpathyContact *contact,
tp_cli_channel_interface_group_call_add_members (priv->channel,
-1, &handles, NULL, NULL, NULL, NULL, NULL);
} else if (priv->can_upgrade_to_muc) {
- EmpathyDispatcher *dispatcher;
- TpConnection *connection;
+ TpAccountChannelRequest *req;
GHashTable *props;
const char *object_path;
GPtrArray channels = { (gpointer *) &object_path, 1 };
const char *invitees[2] = { NULL, };
- dispatcher = empathy_dispatcher_dup_singleton ();
- connection = tp_channel_borrow_connection (priv->channel);
-
invitees[0] = empathy_contact_get_id (contact);
object_path = tp_proxy_get_object_path (priv->channel);
props = tp_asv_new (
- TP_IFACE_CHANNEL ".ChannelType", G_TYPE_STRING,
+ TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
TP_IFACE_CHANNEL_TYPE_TEXT,
- TP_IFACE_CHANNEL ".TargetHandleType", G_TYPE_UINT,
+ TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT,
TP_HANDLE_TYPE_NONE,
- EMP_IFACE_CHANNEL_INTERFACE_CONFERENCE ".InitialChannels",
+ TP_PROP_CHANNEL_INTERFACE_CONFERENCE_INITIAL_CHANNELS,
TP_ARRAY_TYPE_OBJECT_PATH_LIST, &channels,
- EMP_IFACE_CHANNEL_INTERFACE_CONFERENCE ".InitialInviteeIDs",
+ TP_PROP_CHANNEL_INTERFACE_CONFERENCE_INITIAL_INVITEE_IDS,
G_TYPE_STRV, invitees,
/* FIXME: InvitationMessage ? */
NULL);
+ req = tp_account_channel_request_new (priv->account, props,
+ TP_USER_ACTION_TIME_NOT_USER_ACTION);
+
/* Although this is a MUC, it's anonymous, so CreateChannel is
- * valid.
- * props now belongs to EmpathyDispatcher, don't free it */
- empathy_dispatcher_create_channel (dispatcher, connection,
- props, NULL, NULL);
+ * valid. */
+ tp_account_channel_request_create_channel_async (req, NULL, NULL,
+ create_conference_cb, NULL);
- g_object_unref (dispatcher);
+ g_object_unref (req);
+ g_hash_table_unref (props);
} else {
g_warning ("Cannot add to this channel");
}
return members;
}
-static EmpathyContactMonitor *
-tp_chat_get_monitor (EmpathyContactList *list)
+static void
+check_ready (EmpathyTpChat *chat)
{
- EmpathyTpChatPriv *priv;
+ EmpathyTpChatPriv *priv = GET_PRIV (chat);
- g_return_val_if_fail (EMPATHY_IS_TP_CHAT (list), NULL);
+ if (priv->ready)
+ return;
- priv = GET_PRIV (list);
+ if (g_queue_get_length (priv->messages_queue) > 0)
+ return;
- if (priv->contact_monitor == NULL) {
- priv->contact_monitor = empathy_contact_monitor_new_for_iface (list);
- }
+ DEBUG ("Ready");
- return priv->contact_monitor;
+ priv->ready = TRUE;
+ g_object_notify (G_OBJECT (chat), "ready");
}
static void
g_queue_push_tail (priv->pending_messages_queue, message);
g_signal_emit (chat, signals[MESSAGE_RECEIVED], 0, message);
}
+
+ check_ready (chat);
}
static void
-tp_chat_got_sender_cb (EmpathyTpContactFactory *factory,
+tp_chat_got_sender_cb (TpConnection *connection,
EmpathyContact *contact,
const GError *error,
gpointer message,
empathy_message_set_incoming (message, incoming);
empathy_message_set_flags (message, flags);
+ if (flags & TP_CHANNEL_TEXT_MESSAGE_FLAG_SCROLLBACK)
+ empathy_message_set_is_backlog (message, TRUE);
+
g_queue_push_tail (priv->messages_queue, message);
if (from_handle == 0) {
empathy_message_set_sender (message, priv->user);
tp_chat_emit_queued_messages (chat);
} else {
- empathy_tp_contact_factory_get_from_handle (priv->factory,
+ empathy_tp_contact_factory_get_from_handle (priv->connection,
from_handle,
tp_chat_got_sender_cb,
message, NULL, G_OBJECT (chat));
} StateChangedData;
static void
-tp_chat_state_changed_got_contact_cb (EmpathyTpContactFactory *factory,
+tp_chat_state_changed_got_contact_cb (TpConnection *connection,
EmpathyContact *contact,
const GError *error,
gpointer user_data,
state = GPOINTER_TO_UINT (user_data);
DEBUG ("Chat state changed for %s (%d): %d",
- empathy_contact_get_name (contact),
+ empathy_contact_get_alias (contact),
empathy_contact_get_handle (contact), state);
g_signal_emit (chat, signals[CHAT_STATE_CHANGED], 0, contact, state);
{
EmpathyTpChatPriv *priv = GET_PRIV (chat);
- empathy_tp_contact_factory_get_from_handle (priv->factory, handle,
+ empathy_tp_contact_factory_get_from_handle (priv->connection, handle,
tp_chat_state_changed_got_contact_cb, GUINT_TO_POINTER (state),
NULL, chat);
}
acknowledge_messages (chat, empty_non_text_content_ids);
g_array_free (empty_non_text_content_ids, TRUE);
}
+
+ check_ready (chat);
}
static void
priv->dispose_has_run = TRUE;
+ tp_clear_object (&priv->account);
+
+ if (priv->connection != NULL)
+ g_object_unref (priv->connection);
+ priv->connection = NULL;
+
if (priv->channel != NULL) {
g_signal_handlers_disconnect_by_func (priv->channel,
tp_chat_invalidated_cb, self);
g_object_unref (priv->remote_contact);
priv->remote_contact = NULL;
- if (priv->factory != NULL)
- g_object_unref (priv->factory);
- priv->factory = NULL;
-
if (priv->user != NULL)
g_object_unref (priv->user);
priv->user = NULL;
- if (priv->contact_monitor)
- g_object_unref (priv->contact_monitor);
- priv->contact_monitor = NULL;
-
g_queue_foreach (priv->messages_queue, (GFunc) g_object_unref, NULL);
g_queue_clear (priv->messages_queue);
}
static void
-tp_chat_check_if_ready (EmpathyTpChat *chat)
+check_almost_ready (EmpathyTpChat *chat)
{
EmpathyTpChatPriv *priv = GET_PRIV (chat);
priv->remote_contact == NULL)
return;
- DEBUG ("Ready!");
-
tp_cli_channel_type_text_connect_to_received (priv->channel,
tp_chat_received_cb,
NULL, NULL,
G_OBJECT (chat), NULL);
priv->listing_pending_messages = TRUE;
+
+ /* TpChat will be ready once ListPendingMessages returned and all the messages
+ * have been added to the pending messages queue. */
tp_cli_channel_type_text_call_list_pending_messages (priv->channel, -1,
FALSE,
tp_chat_list_pending_messages_cb,
tp_chat_state_changed_cb,
NULL, NULL,
G_OBJECT (chat), NULL);
- priv->ready = TRUE;
- g_object_notify (G_OBJECT (chat), "ready");
}
static void
* have the group interface. If it has the conference interface, then
* it is indeed a MUC. */
if (tp_proxy_has_interface_by_id (priv->channel,
- EMP_IFACE_QUARK_CHANNEL_INTERFACE_CONFERENCE)) {
+ TP_IFACE_QUARK_CHANNEL_INTERFACE_CONFERENCE)) {
return;
}
}
static void
-tp_chat_got_added_contacts_cb (EmpathyTpContactFactory *factory,
+tp_chat_got_added_contacts_cb (TpConnection *connection,
guint n_contacts,
EmpathyContact * const * contacts,
guint n_failed,
}
tp_chat_update_remote_contact (EMPATHY_TP_CHAT (chat));
- tp_chat_check_if_ready (EMPATHY_TP_CHAT (chat));
+ check_almost_ready (EMPATHY_TP_CHAT (chat));
}
static EmpathyContact *
}
static void
-tp_chat_got_renamed_contacts_cb (EmpathyTpContactFactory *factory,
+tp_chat_got_renamed_contacts_cb (TpConnection *connection,
guint n_contacts,
EmpathyContact * const * contacts,
guint n_failed,
}
tp_chat_update_remote_contact (EMPATHY_TP_CHAT (chat));
- tp_chat_check_if_ready (EMPATHY_TP_CHAT (chat));
+ check_almost_ready (EMPATHY_TP_CHAT (chat));
}
/* Contact renamed */
if (reason == TP_CHANNEL_GROUP_CHANGE_REASON_RENAMED) {
/* there can only be a single 'added' and a single 'removed' handle */
- g_warn_if_fail (removed->len == 1);
- g_warn_if_fail (added->len == 1);
+ if (removed->len != 1 || added->len != 1) {
+ g_warning ("RENAMED with %u added, %u removed (expected 1, 1)",
+ added->len, removed->len);
+ return;
+ }
old_handle = g_array_index (removed, guint, 0);
rename_data = contact_rename_data_new (old_handle, reason, message);
- empathy_tp_contact_factory_get_from_handles (priv->factory,
+ empathy_tp_contact_factory_get_from_handles (priv->connection,
added->len, (TpHandle *) added->data,
tp_chat_got_renamed_contacts_cb,
rename_data, (GDestroyNotify) contact_rename_data_free,
/* Request added contacts */
if (added->len > 0) {
- empathy_tp_contact_factory_get_from_handles (priv->factory,
+ empathy_tp_contact_factory_get_from_handles (priv->connection,
added->len, (TpHandle *) added->data,
tp_chat_got_added_contacts_cb, NULL, NULL,
G_OBJECT (chat));
}
static void
-tp_chat_got_remote_contact_cb (EmpathyTpContactFactory *factory,
+tp_chat_got_remote_contact_cb (TpConnection *connection,
EmpathyContact *contact,
const GError *error,
gpointer user_data,
priv->remote_contact = g_object_ref (contact);
g_object_notify (chat, "remote-contact");
- tp_chat_check_if_ready (EMPATHY_TP_CHAT (chat));
+ check_almost_ready (EMPATHY_TP_CHAT (chat));
}
static void
-tp_chat_got_self_contact_cb (EmpathyTpContactFactory *factory,
+tp_chat_got_self_contact_cb (TpConnection *connection,
EmpathyContact *contact,
const GError *error,
gpointer user_data,
priv->user = g_object_ref (contact);
empathy_contact_set_is_user (priv->user, TRUE);
- tp_chat_check_if_ready (EMPATHY_TP_CHAT (chat));
+ check_almost_ready (EMPATHY_TP_CHAT (chat));
}
static void
priv->got_password_flags = TRUE;
priv->password_flags = password_flags;
- tp_chat_check_if_ready (EMPATHY_TP_CHAT (self));
+ check_almost_ready (EMPATHY_TP_CHAT (self));
}
static GObject *
{
GObject *chat;
EmpathyTpChatPriv *priv;
- TpConnection *connection;
TpHandle handle;
chat = G_OBJECT_CLASS (empathy_tp_chat_parent_class)->constructor (type, n_props, props);
priv = GET_PRIV (chat);
- connection = tp_channel_borrow_connection (priv->channel);
- priv->factory = empathy_tp_contact_factory_dup_singleton (connection);
- g_signal_connect (priv->channel, "invalidated",
+ priv->connection = g_object_ref (tp_account_get_connection (priv->account));
+ tp_g_signal_connect_object (priv->channel, "invalidated",
G_CALLBACK (tp_chat_invalidated_cb),
- chat);
+ chat, 0);
+
+ g_assert (tp_proxy_is_prepared (priv->connection,
+ TP_CONNECTION_FEATURE_CAPABILITIES));
if (tp_proxy_has_interface_by_id (priv->channel,
TP_IFACE_QUARK_CHANNEL_INTERFACE_GROUP)) {
/* Get self contact from the group's self handle */
handle = tp_channel_group_get_self_handle (priv->channel);
- empathy_tp_contact_factory_get_from_handle (priv->factory,
+ empathy_tp_contact_factory_get_from_handle (priv->connection,
handle, tp_chat_got_self_contact_cb,
NULL, NULL, chat);
/* Get initial member contacts */
members = tp_channel_group_get_members (priv->channel);
handles = tp_intset_to_array (members);
- empathy_tp_contact_factory_get_from_handles (priv->factory,
+ empathy_tp_contact_factory_get_from_handles (priv->connection,
handles->len, (TpHandle *) handles->data,
tp_chat_got_added_contacts_cb, NULL, NULL, chat);
priv->can_upgrade_to_muc = FALSE;
- g_signal_connect (priv->channel, "group-members-changed",
- G_CALLBACK (tp_chat_group_members_changed_cb), chat);
+ tp_g_signal_connect_object (priv->channel, "group-members-changed",
+ G_CALLBACK (tp_chat_group_members_changed_cb), chat, 0);
} else {
- EmpathyDispatcher *dispatcher = empathy_dispatcher_dup_singleton ();
- GList *list, *ptr;
+ TpCapabilities *caps;
+ GPtrArray *classes;
+ guint i;
/* Get the self contact from the connection's self handle */
- handle = tp_connection_get_self_handle (connection);
- empathy_tp_contact_factory_get_from_handle (priv->factory,
+ handle = tp_connection_get_self_handle (priv->connection);
+ empathy_tp_contact_factory_get_from_handle (priv->connection,
handle, tp_chat_got_self_contact_cb,
NULL, NULL, chat);
/* Get the remote contact */
handle = tp_channel_get_handle (priv->channel, NULL);
- empathy_tp_contact_factory_get_from_handle (priv->factory,
+ empathy_tp_contact_factory_get_from_handle (priv->connection,
handle, tp_chat_got_remote_contact_cb,
NULL, NULL, chat);
- list = empathy_dispatcher_find_requestable_channel_classes (
- dispatcher, connection,
- tp_channel_get_channel_type (priv->channel),
- TP_UNKNOWN_HANDLE_TYPE, NULL);
+ caps = tp_connection_get_capabilities (priv->connection);
+ g_assert (caps != NULL);
+
+ classes = tp_capabilities_get_channel_classes (caps);
- for (ptr = list; ptr; ptr = ptr->next) {
- GValueArray *array = ptr->data;
+ for (i = 0; i < classes->len; i++) {
+ GValueArray *array = g_ptr_array_index (classes, i);
const char **oprops = g_value_get_boxed (
g_value_array_get_nth (array, 1));
- if (tp_strv_contains (oprops, EMP_IFACE_CHANNEL_INTERFACE_CONFERENCE ".InitialChannels")) {
+ if (tp_strv_contains (oprops, TP_PROP_CHANNEL_INTERFACE_CONFERENCE_INITIAL_CHANNELS)) {
priv->can_upgrade_to_muc = TRUE;
break;
}
}
-
- g_list_free (list);
- g_object_unref (dispatcher);
}
if (tp_proxy_has_interface_by_id (priv->channel,
EmpathyTpChatPriv *priv = GET_PRIV (object);
switch (param_id) {
+ case PROP_ACCOUNT:
+ g_value_set_object (value, priv->account);
+ break;
case PROP_CHANNEL:
g_value_set_object (value, priv->channel);
break;
EmpathyTpChatPriv *priv = GET_PRIV (object);
switch (param_id) {
+ case PROP_ACCOUNT:
+ priv->account = g_value_dup_object (value);
+ break;
case PROP_CHANNEL:
priv->channel = g_value_dup_object (value);
break;
object_class->get_property = tp_chat_get_property;
object_class->set_property = tp_chat_set_property;
+ g_object_class_install_property (object_class,
+ PROP_ACCOUNT,
+ g_param_spec_object ("account",
+ "TpAccount",
+ "the account associated with the chat",
+ TP_TYPE_ACCOUNT,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
g_object_class_install_property (object_class,
PROP_CHANNEL,
g_param_spec_object ("channel",
EMPATHY_TYPE_TP_CHAT, EmpathyTpChatPriv);
chat->priv = priv;
- priv->contact_monitor = NULL;
priv->messages_queue = g_queue_new ();
priv->pending_messages_queue = g_queue_new ();
}
iface->add = tp_chat_add;
iface->remove = tp_chat_remove;
iface->get_members = tp_chat_get_members;
- iface->get_monitor = tp_chat_get_monitor;
}
EmpathyTpChat *
-empathy_tp_chat_new (TpChannel *channel)
+empathy_tp_chat_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_CHAT,
+ "account", account,
"channel", channel,
NULL);
}
return priv->channel;
}
+TpAccount *
+empathy_tp_chat_get_account (EmpathyTpChat *chat)
+{
+ EmpathyTpChatPriv *priv = GET_PRIV (chat);
+
+ g_return_val_if_fail (EMPATHY_IS_TP_CHAT (chat), NULL);
+
+ return priv->account;
+}
+
TpConnection *
empathy_tp_chat_get_connection (EmpathyTpChat *chat)
{
return tp_channel_borrow_connection (priv->channel);
}
-
gboolean
empathy_tp_chat_is_ready (EmpathyTpChat *chat)
{
g_array_free (array, TRUE);
}
+
+static void
+add_members_cb (TpChannel *proxy,
+ const GError *error,
+ gpointer user_data,
+ GObject *weak_object)
+{
+ EmpathyTpChatPriv *priv = GET_PRIV (weak_object);
+
+ if (error != NULL) {
+ DEBUG ("Failed to join chat (%s): %s",
+ tp_channel_get_identifier (priv->channel), error->message);
+ }
+}
+
+void
+empathy_tp_chat_join (EmpathyTpChat *self)
+{
+ EmpathyTpChatPriv *priv = GET_PRIV (self);
+ TpHandle self_handle;
+ GArray *members;
+
+ self_handle = tp_channel_group_get_self_handle (priv->channel);
+
+ members = g_array_sized_new (FALSE, FALSE, sizeof (TpHandle), 1);
+ g_array_append_val (members, self_handle);
+
+ tp_cli_channel_interface_group_call_add_members (priv->channel, -1, members,
+ "", add_members_cb, NULL, NULL, G_OBJECT (self));
+
+ g_array_free (members, TRUE);
+}
+
+gboolean
+empathy_tp_chat_is_invited (EmpathyTpChat *self,
+ TpHandle *inviter)
+{
+ EmpathyTpChatPriv *priv = GET_PRIV (self);
+ TpHandle self_handle;
+
+ if (!tp_proxy_has_interface (priv->channel, TP_IFACE_CHANNEL_INTERFACE_GROUP))
+ return FALSE;
+
+ self_handle = tp_channel_group_get_self_handle (priv->channel);
+ if (self_handle == 0)
+ return FALSE;
+
+ return tp_channel_group_get_local_pending_info (priv->channel, self_handle,
+ inviter, NULL, NULL);
+}