#include <string.h>
-#include <telepathy-glib/channel.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/util.h>
-#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/telepathy-glib.h>
+
+#include <extensions/extensions.h>
#include "empathy-tp-chat.h"
#include "empathy-tp-contact-factory.h"
-#include "empathy-contact-monitor.h"
#include "empathy-contact-list.h"
#include "empathy-marshal.h"
#include "empathy-time.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;
* (channel doesn't implement the Password interface) */
gboolean got_password_flags;
gboolean ready;
+ gboolean can_upgrade_to_muc;
} EmpathyTpChatPriv;
static void tp_chat_iface_init (EmpathyContactListIface *iface);
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,
const gchar *message)
{
EmpathyTpChatPriv *priv = GET_PRIV (list);
- TpHandle handle;
- GArray handles = {(gchar *) &handle, 1};
- g_return_if_fail (EMPATHY_IS_TP_CHAT (list));
- g_return_if_fail (EMPATHY_IS_CONTACT (contact));
+ if (tp_proxy_has_interface_by_id (priv->channel,
+ TP_IFACE_QUARK_CHANNEL_INTERFACE_GROUP)) {
+ TpHandle handle;
+ GArray handles = {(gchar *) &handle, 1};
- handle = empathy_contact_get_handle (contact);
- tp_cli_channel_interface_group_call_add_members (priv->channel, -1,
- &handles, NULL,
- NULL, NULL, NULL,
- NULL);
+ g_return_if_fail (EMPATHY_IS_TP_CHAT (list));
+ g_return_if_fail (EMPATHY_IS_CONTACT (contact));
+
+ handle = empathy_contact_get_handle (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) {
+ TpAccountChannelRequest *req;
+ GHashTable *props;
+ const char *object_path;
+ GPtrArray channels = { (gpointer *) &object_path, 1 };
+ const char *invitees[2] = { NULL, };
+
+ invitees[0] = empathy_contact_get_id (contact);
+ object_path = tp_proxy_get_object_path (priv->channel);
+
+ props = tp_asv_new (
+ TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
+ TP_IFACE_CHANNEL_TYPE_TEXT,
+ TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT,
+ TP_HANDLE_TYPE_NONE,
+ TP_PROP_CHANNEL_INTERFACE_CONFERENCE_INITIAL_CHANNELS,
+ TP_ARRAY_TYPE_OBJECT_PATH_LIST, &channels,
+ 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. */
+ tp_account_channel_request_create_channel_async (req, NULL, NULL,
+ create_conference_cb, NULL);
+
+ g_object_unref (req);
+ g_hash_table_unref (props);
+ } else {
+ g_warning ("Cannot add to this channel");
+ }
}
static void
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,
guint type,
guint timestamp,
guint from_handle,
- const gchar *message_body)
+ const gchar *message_body,
+ TpChannelTextMessageFlags flags)
{
EmpathyTpChatPriv *priv;
EmpathyMessage *message;
empathy_message_set_timestamp (message, timestamp);
empathy_message_set_id (message, id);
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);
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));
message_type,
timestamp,
from_handle,
- message_body);
+ message_body,
+ message_flags);
}
static void
message_type,
timestamp,
0,
- message_body);
+ message_body,
+ 0);
}
static void
} 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);
}
message_type,
timestamp,
from_handle,
- message_body);
+ message_body,
+ message_flags);
}
if (empty_non_text_content_ids != NULL) {
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);
* If the chat is protected by a password we can't get these information so
* consider the chat as ready so it can be presented to the user. */
if (!empathy_tp_chat_password_needed (chat) && priv->members == NULL &&
- priv->remote_contact == NULL)
+ 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);
- tp_cli_channel_interface_chat_state_connect_to_chat_state_changed (priv->channel,
- tp_chat_state_changed_cb,
- NULL, NULL,
- G_OBJECT (chat), NULL);
- priv->ready = TRUE;
- g_object_notify (G_OBJECT (chat), "ready");
}
static void
return;
}
+ /* This is an MSN chat, but it's the new style where 1-1 chats don't
+ * 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,
+ TP_IFACE_QUARK_CHANNEL_INTERFACE_CONFERENCE)) {
+ return;
+ }
+
/* This is an MSN-like chat where anyone can join the chat at anytime.
* If there is only one non-self contact member, we are in a private
* chat and we set the "remote-contact" property to that contact. If
}
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 *
return NULL;
}
+typedef struct
+{
+ TpHandle old_handle;
+ guint reason;
+ gchar *message;
+} ContactRenameData;
+
+static ContactRenameData *
+contact_rename_data_new (TpHandle handle,
+ guint reason,
+ const gchar* message)
+{
+ ContactRenameData *data = g_new (ContactRenameData, 1);
+ data->old_handle = handle;
+ data->reason = reason;
+ data->message = g_strdup (message);
+
+ return data;
+}
+
+static void
+contact_rename_data_free (ContactRenameData* data)
+{
+ g_free (data->message);
+ g_free (data);
+}
+
+static void
+tp_chat_got_renamed_contacts_cb (TpConnection *connection,
+ guint n_contacts,
+ EmpathyContact * const * contacts,
+ guint n_failed,
+ const TpHandle *failed,
+ const GError *error,
+ gpointer user_data,
+ GObject *chat)
+{
+ EmpathyTpChatPriv *priv = GET_PRIV (chat);
+ const TpIntSet *members;
+ TpHandle handle;
+ EmpathyContact *old = NULL, *new = NULL;
+ ContactRenameData *rename_data = (ContactRenameData *) user_data;
+
+ if (error) {
+ DEBUG ("Error: %s", error->message);
+ return;
+ }
+
+ /* renamed members can only be delivered one at a time */
+ g_warn_if_fail (n_contacts == 1);
+
+ new = contacts[0];
+
+ members = tp_channel_group_get_members (priv->channel);
+ handle = empathy_contact_get_handle (new);
+
+ old = chat_lookup_contact (EMPATHY_TP_CHAT (chat),
+ rename_data->old_handle, TRUE);
+
+ /* Make sure the contact is still member */
+ if (tp_intset_is_member (members, handle)) {
+ priv->members = g_list_prepend (priv->members,
+ g_object_ref (new));
+
+ if (old != NULL) {
+ g_signal_emit_by_name (chat, "member-renamed",
+ old, new, rename_data->reason,
+ rename_data->message);
+ g_object_unref (old);
+ }
+ }
+
+ if (priv->user == old) {
+ /* We change our nick */
+ g_object_unref (priv->user);
+ priv->user = g_object_ref (new);
+ }
+
+ tp_chat_update_remote_contact (EMPATHY_TP_CHAT (chat));
+ check_almost_ready (EMPATHY_TP_CHAT (chat));
+}
+
+
static void
tp_chat_group_members_changed_cb (TpChannel *self,
gchar *message,
EmpathyContact *contact;
EmpathyContact *actor_contact = NULL;
guint i;
+ ContactRenameData *rename_data;
+ TpHandle old_handle;
+
+ /* Contact renamed */
+ if (reason == TP_CHANNEL_GROUP_CHANGE_REASON_RENAMED) {
+ /* there can only be a single 'added' and a single 'removed' handle */
+ 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->connection,
+ added->len, (TpHandle *) added->data,
+ tp_chat_got_renamed_contacts_cb,
+ rename_data, (GDestroyNotify) contact_rename_data_free,
+ G_OBJECT (chat));
+ return;
+ }
if (actor != 0) {
actor_contact = chat_lookup_contact (chat, actor, FALSE);
/* 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,
if (error) {
DEBUG ("Error: %s", error->message);
- empathy_tp_chat_close (EMPATHY_TP_CHAT (chat));
+ empathy_tp_chat_leave (EMPATHY_TP_CHAT (chat));
return;
}
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,
if (error) {
DEBUG ("Error: %s", error->message);
- empathy_tp_chat_close (EMPATHY_TP_CHAT (chat));
+ empathy_tp_chat_leave (EMPATHY_TP_CHAT (chat));
return;
}
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);
- g_signal_connect (priv->channel, "group-members-changed",
- G_CALLBACK (tp_chat_group_members_changed_cb), chat);
+ priv->can_upgrade_to_muc = FALSE;
+
+ tp_g_signal_connect_object (priv->channel, "group-members-changed",
+ G_CALLBACK (tp_chat_group_members_changed_cb), chat, 0);
} else {
+ 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);
+
+ caps = tp_connection_get_capabilities (priv->connection);
+ g_assert (caps != NULL);
+
+ classes = tp_capabilities_get_channel_classes (caps);
+
+ 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, TP_PROP_CHANNEL_INTERFACE_CONFERENCE_INITIAL_CHANNELS)) {
+ priv->can_upgrade_to_muc = TRUE;
+ break;
+ }
+ }
}
if (tp_proxy_has_interface_by_id (priv->channel,
TP_IFACE_QUARK_CHANNEL_INTERFACE_PASSWORD)) {
priv->got_password_flags = FALSE;
- tp_cli_channel_interface_password_connect_to_password_flags_changed (
- priv->channel, password_flags_changed_cb, chat, NULL,
- G_OBJECT (chat), NULL);
+ tp_cli_channel_interface_password_connect_to_password_flags_changed
+ (priv->channel, password_flags_changed_cb, chat, NULL,
+ G_OBJECT (chat), NULL);
- tp_cli_channel_interface_password_call_get_password_flags (priv->channel,
- -1, got_password_flags_cb, chat, NULL, chat);
+ tp_cli_channel_interface_password_call_get_password_flags
+ (priv->channel, -1, got_password_flags_cb, chat, NULL, chat);
} else {
/* No Password interface, so no need to fetch the password flags */
priv->got_password_flags = TRUE;
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);
}
-void
+static void
empathy_tp_chat_close (EmpathyTpChat *chat) {
EmpathyTpChatPriv *priv = GET_PRIV (chat);
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)
{
void
empathy_tp_chat_acknowledge_messages (EmpathyTpChat *chat,
- const GList *messages) {
+ const GSList *messages) {
EmpathyTpChatPriv *priv = GET_PRIV (chat);
/* Copy messages as the messges list (probably is) our own */
- GList *msgs = g_list_copy ((GList *) messages);
- GList *l;
+ GSList *msgs = g_slist_copy ((GSList *) messages);
+ GSList *l;
guint length;
GArray *message_ids;
g_return_if_fail (EMPATHY_IS_TP_CHAT (chat));
g_return_if_fail (priv->ready);
- length = g_list_length ((GList *) messages);
+ length = g_slist_length ((GSList *) messages);
if (length == 0)
return;
message_ids = g_array_sized_new (FALSE, FALSE, sizeof (guint), length);
- for (l = msgs; l != NULL; l = g_list_next (l)) {
+ for (l = msgs; l != NULL; l = g_slist_next (l)) {
GList *m;
EmpathyMessage *message = EMPATHY_MESSAGE (l->data);
acknowledge_messages (chat, message_ids);
g_array_free (message_ids, TRUE);
- g_list_free (msgs);
+ g_slist_free (msgs);
+}
+
+void
+empathy_tp_chat_acknowledge_all_messages (EmpathyTpChat *chat)
+{
+ empathy_tp_chat_acknowledge_messages (chat,
+ (GSList *) empathy_tp_chat_get_pending_messages (chat));
}
gboolean
GSimpleAsyncResult *result = user_data;
if (error != NULL) {
- g_simple_async_result_set_from_error (result, error);
+ g_simple_async_result_set_from_error (result, error);
}
else if (!correct) {
- /* The current D-Bus API is a bit weird so re-use the
- * AuthenticationFailed error */
- g_simple_async_result_set_error (result, TP_ERRORS,
- TP_ERROR_AUTHENTICATION_FAILED, "Wrong password");
+ /* The current D-Bus API is a bit weird so re-use the
+ * AuthenticationFailed error */
+ g_simple_async_result_set_error (result, TP_ERRORS,
+ TP_ERROR_AUTHENTICATION_FAILED, "Wrong password");
}
g_simple_async_result_complete (result);
GSimpleAsyncResult *result;
result = g_simple_async_result_new (G_OBJECT (self),
- callback, user_data, empathy_tp_chat_provide_password_finish);
+ callback, user_data,
+ empathy_tp_chat_provide_password_finish);
- tp_cli_channel_interface_password_call_provide_password (priv->channel, -1,
- password, provide_password_cb, result, NULL, G_OBJECT (self));
+ tp_cli_channel_interface_password_call_provide_password
+ (priv->channel, -1, password, provide_password_cb, result,
+ NULL, G_OBJECT (self));
}
gboolean
return FALSE;
g_return_val_if_fail (g_simple_async_result_is_valid (result,
- G_OBJECT (self), empathy_tp_chat_provide_password_finish), FALSE);
+ G_OBJECT (self), empathy_tp_chat_provide_password_finish), FALSE);
return TRUE;
}
+
+/**
+ * empathy_tp_chat_can_add_contact:
+ *
+ * Returns: %TRUE if empathy_contact_list_add() will work for this channel.
+ * That is if this chat is a 1-to-1 channel that can be upgraded to
+ * a MUC using the Conference interface or if the channel is a MUC.
+ */
+gboolean
+empathy_tp_chat_can_add_contact (EmpathyTpChat *self)
+{
+ EmpathyTpChatPriv *priv;
+
+ g_return_val_if_fail (EMPATHY_IS_TP_CHAT (self), FALSE);
+
+ priv = GET_PRIV (self);
+
+ return priv->can_upgrade_to_muc ||
+ tp_proxy_has_interface_by_id (priv->channel,
+ TP_IFACE_QUARK_CHANNEL_INTERFACE_GROUP);;
+}
+
+static void
+leave_remove_members_cb (TpChannel *proxy,
+ const GError *error,
+ gpointer user_data,
+ GObject *weak_object)
+{
+ EmpathyTpChat *self = user_data;
+
+ if (error == NULL)
+ return;
+
+ DEBUG ("RemoveMembers failed (%s); closing the channel", error->message);
+ empathy_tp_chat_close (self);
+}
+
+void
+empathy_tp_chat_leave (EmpathyTpChat *self)
+{
+ EmpathyTpChatPriv *priv = GET_PRIV (self);
+ TpHandle self_handle;
+ GArray *array;
+
+ if (!tp_proxy_has_interface_by_id (priv->channel,
+ TP_IFACE_QUARK_CHANNEL_INTERFACE_GROUP)) {
+ empathy_tp_chat_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_chat_close (self);
+ return;
+ }
+
+ array = g_array_sized_new (FALSE, FALSE, sizeof (TpHandle), 1);
+ g_array_insert_val (array, 0, self_handle);
+
+ tp_cli_channel_interface_group_call_remove_members (priv->channel, -1, array,
+ "", leave_remove_members_cb, self, NULL, G_OBJECT (self));
+
+ 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);
+}