aboutsummaryrefslogtreecommitdiffstats
path: root/libempathy
diff options
context:
space:
mode:
Diffstat (limited to 'libempathy')
-rw-r--r--libempathy/empathy-contact-list.c58
-rw-r--r--libempathy/empathy-contact-list.h52
-rw-r--r--libempathy/empathy-contact-manager.c78
-rw-r--r--libempathy/empathy-idle.c233
-rw-r--r--libempathy/empathy-idle.h15
-rw-r--r--libempathy/empathy-marshal.list8
-rw-r--r--libempathy/empathy-tp-chatroom.c14
-rw-r--r--libempathy/empathy-tp-contact-list.c355
8 files changed, 598 insertions, 215 deletions
diff --git a/libempathy/empathy-contact-list.c b/libempathy/empathy-contact-list.c
index b7d02010b..c55d0abf9 100644
--- a/libempathy/empathy-contact-list.c
+++ b/libempathy/empathy-contact-list.c
@@ -23,6 +23,7 @@
#include "config.h"
#include "empathy-contact-list.h"
+#include "empathy-marshal.h"
static void contact_list_base_init (gpointer klass);
@@ -70,10 +71,49 @@ contact_list_base_init (gpointer klass)
G_TYPE_NONE,
1, GOSSIP_TYPE_CONTACT);
+ g_signal_new ("local-pending",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ empathy_marshal_VOID__OBJECT_STRING,
+ G_TYPE_NONE,
+ 2, GOSSIP_TYPE_CONTACT, G_TYPE_STRING);
+
initialized = TRUE;
}
}
+EmpathyContactListInfo *
+empathy_contact_list_info_new (GossipContact *contact,
+ const gchar *message)
+{
+ EmpathyContactListInfo *info;
+
+ g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), NULL);
+
+ info = g_slice_new0 (EmpathyContactListInfo);
+ info->contact = g_object_ref (contact);
+ info->message = g_strdup (message);
+
+ return info;
+}
+
+void
+empathy_contact_list_info_free (EmpathyContactListInfo *info)
+{
+ if (!info) {
+ return;
+ }
+
+ if (info->contact) {
+ g_object_unref (info->contact);
+ }
+ g_free (info->message);
+
+ g_slice_free (EmpathyContactListInfo, info);
+}
+
void
empathy_contact_list_setup (EmpathyContactList *list)
{
@@ -122,12 +162,24 @@ empathy_contact_list_remove (EmpathyContactList *list,
}
GList *
-empathy_contact_list_get_contacts (EmpathyContactList *list)
+empathy_contact_list_get_members (EmpathyContactList *list)
+{
+ g_return_val_if_fail (EMPATHY_IS_CONTACT_LIST (list), NULL);
+
+ if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_members) {
+ return EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_members (list);
+ }
+
+ return NULL;
+}
+
+GList *
+empathy_contact_list_get_local_pending (EmpathyContactList *list)
{
g_return_val_if_fail (EMPATHY_IS_CONTACT_LIST (list), NULL);
- if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_contacts) {
- return EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_contacts (list);
+ if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_local_pending) {
+ return EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_local_pending (list);
}
return NULL;
diff --git a/libempathy/empathy-contact-list.h b/libempathy/empathy-contact-list.h
index 02ec3186d..09f54621d 100644
--- a/libempathy/empathy-contact-list.h
+++ b/libempathy/empathy-contact-list.h
@@ -37,33 +37,43 @@ G_BEGIN_DECLS
typedef struct _EmpathyContactList EmpathyContactList;
typedef struct _EmpathyContactListIface EmpathyContactListIface;
+typedef struct {
+ GossipContact *contact;
+ gchar *message;
+} EmpathyContactListInfo;
+
struct _EmpathyContactListIface {
GTypeInterface base_iface;
/* VTabled */
- void (*setup) (EmpathyContactList *list);
- GossipContact * (*find) (EmpathyContactList *list,
- const gchar *id);
- void (*add) (EmpathyContactList *list,
- GossipContact *contact,
- const gchar *message);
- void (*remove) (EmpathyContactList *list,
- GossipContact *contact,
- const gchar *message);
- GList * (*get_contacts) (EmpathyContactList *list);
+ void (*setup) (EmpathyContactList *list);
+ GossipContact * (*find) (EmpathyContactList *list,
+ const gchar *id);
+ void (*add) (EmpathyContactList *list,
+ GossipContact *contact,
+ const gchar *message);
+ void (*remove) (EmpathyContactList *list,
+ GossipContact *contact,
+ const gchar *message);
+ GList * (*get_members) (EmpathyContactList *list);
+ GList * (*get_local_pending) (EmpathyContactList *list);
};
-GType empathy_contact_list_get_type (void) G_GNUC_CONST;
-void empathy_contact_list_setup (EmpathyContactList *list);
-GossipContact * empathy_contact_list_find (EmpathyContactList *list,
- const gchar *id);
-void empathy_contact_list_add (EmpathyContactList *list,
- GossipContact *contact,
- const gchar *message);
-void empathy_contact_list_remove (EmpathyContactList *list,
- GossipContact *contact,
- const gchar *message);
-GList * empathy_contact_list_get_contacts (EmpathyContactList *list);
+GType empathy_contact_list_get_type (void) G_GNUC_CONST;
+EmpathyContactListInfo *empathy_contact_list_info_new (GossipContact *contact,
+ const gchar *message);
+void empathy_contact_list_info_free (EmpathyContactListInfo *info);
+void empathy_contact_list_setup (EmpathyContactList *list);
+GossipContact * empathy_contact_list_find (EmpathyContactList *list,
+ const gchar *id);
+void empathy_contact_list_add (EmpathyContactList *list,
+ GossipContact *contact,
+ const gchar *message);
+void empathy_contact_list_remove (EmpathyContactList *list,
+ GossipContact *contact,
+ const gchar *message);
+GList * empathy_contact_list_get_members (EmpathyContactList *list);
+GList * empathy_contact_list_get_local_pending (EmpathyContactList *list);
G_END_DECLS
diff --git a/libempathy/empathy-contact-manager.c b/libempathy/empathy-contact-manager.c
index fa62da98f..5e5f09a43 100644
--- a/libempathy/empathy-contact-manager.c
+++ b/libempathy/empathy-contact-manager.c
@@ -65,7 +65,8 @@ static void contact_manager_add (EmpathyContactList
static void contact_manager_remove (EmpathyContactList *manager,
GossipContact *contact,
const gchar *message);
-static GList * contact_manager_get_contacts (EmpathyContactList *manager);
+static GList * contact_manager_get_members (EmpathyContactList *manager);
+static GList * contact_manager_get_local_pending (EmpathyContactList *manager);
static void contact_manager_setup_foreach (McAccount *account,
EmpathyTpContactList *list,
EmpathyContactManager *manager);
@@ -80,6 +81,10 @@ static void contact_manager_added_cb (EmpathyTpContactList
static void contact_manager_removed_cb (EmpathyTpContactList *list,
GossipContact *contact,
EmpathyContactManager *manager);
+static void contact_manager_local_pending_cb (EmpathyTpContactList *list,
+ GossipContact *contact,
+ const gchar *message,
+ EmpathyContactManager *manager);
static void contact_manager_destroy_cb (EmpathyTpContactList *list,
EmpathyContactManager *manager);
static void contact_manager_rename_group_foreach (McAccount *account,
@@ -88,7 +93,10 @@ static void contact_manager_rename_group_foreach (McAccount
static void contact_manager_get_groups_foreach (McAccount *account,
EmpathyTpContactList *list,
GList **all_groups);
-static void contact_manager_get_contacts_foreach (McAccount *account,
+static void contact_manager_get_members_foreach (McAccount *account,
+ EmpathyTpContactList *list,
+ GList **contacts);
+static void contact_manager_get_local_pending_foreach (McAccount *account,
EmpathyTpContactList *list,
GList **contacts);
static void contact_manager_status_changed_cb (MissionControl *mc,
@@ -115,11 +123,12 @@ empathy_contact_manager_class_init (EmpathyContactManagerClass *klass)
static void
contact_manager_iface_init (EmpathyContactListIface *iface)
{
- iface->setup = contact_manager_setup;
- iface->find = contact_manager_find;
- iface->add = contact_manager_add;
- iface->remove = contact_manager_remove;
- iface->get_contacts = contact_manager_get_contacts;
+ iface->setup = contact_manager_setup;
+ iface->find = contact_manager_find;
+ iface->add = contact_manager_add;
+ iface->remove = contact_manager_remove;
+ iface->get_members = contact_manager_get_members;
+ iface->get_local_pending = contact_manager_get_local_pending;
}
static void
@@ -269,7 +278,7 @@ contact_manager_remove (EmpathyContactList *manager,
}
static GList *
-contact_manager_get_contacts (EmpathyContactList *manager)
+contact_manager_get_members (EmpathyContactList *manager)
{
EmpathyContactManagerPriv *priv;
GList *contacts = NULL;
@@ -279,12 +288,29 @@ contact_manager_get_contacts (EmpathyContactList *manager)
priv = GET_PRIV (manager);
g_hash_table_foreach (priv->lists,
- (GHFunc) contact_manager_get_contacts_foreach,
+ (GHFunc) contact_manager_get_members_foreach,
&contacts);
return contacts;
}
+static GList *
+contact_manager_get_local_pending (EmpathyContactList *manager)
+{
+ EmpathyContactManagerPriv *priv;
+ GList *pending = NULL;
+
+ g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), NULL);
+
+ priv = GET_PRIV (manager);
+
+ g_hash_table_foreach (priv->lists,
+ (GHFunc) contact_manager_get_local_pending_foreach,
+ &pending);
+
+ return pending;
+}
+
EmpathyTpContactList *
empathy_contact_manager_get_list (EmpathyContactManager *manager,
McAccount *account)
@@ -435,6 +461,9 @@ contact_manager_add_account (EmpathyContactManager *manager,
g_signal_connect (list, "contact-removed",
G_CALLBACK (contact_manager_removed_cb),
manager);
+ g_signal_connect (list, "local-pending",
+ G_CALLBACK (contact_manager_local_pending_cb),
+ manager);
g_signal_connect (list, "destroy",
G_CALLBACK (contact_manager_destroy_cb),
manager);
@@ -461,6 +490,15 @@ contact_manager_removed_cb (EmpathyTpContactList *list,
}
static void
+contact_manager_local_pending_cb (EmpathyTpContactList *list,
+ GossipContact *contact,
+ const gchar *message,
+ EmpathyContactManager *manager)
+{
+ g_signal_emit_by_name (manager, "local-pending", contact, message);
+}
+
+static void
contact_manager_destroy_cb (EmpathyTpContactList *list,
EmpathyContactManager *manager)
{
@@ -482,6 +520,9 @@ contact_manager_destroy_cb (EmpathyTpContactList *list,
contact_manager_removed_cb,
manager);
g_signal_handlers_disconnect_by_func (list,
+ contact_manager_local_pending_cb,
+ manager);
+ g_signal_handlers_disconnect_by_func (list,
contact_manager_destroy_cb,
manager);
@@ -520,13 +561,24 @@ contact_manager_get_groups_foreach (McAccount *account,
}
static void
-contact_manager_get_contacts_foreach (McAccount *account,
- EmpathyTpContactList *list,
- GList **contacts)
+contact_manager_get_members_foreach (McAccount *account,
+ EmpathyTpContactList *list,
+ GList **contacts)
+{
+ GList *l;
+
+ l = empathy_contact_list_get_members (EMPATHY_CONTACT_LIST (list));
+ *contacts = g_list_concat (*contacts, l);
+}
+
+static void
+contact_manager_get_local_pending_foreach (McAccount *account,
+ EmpathyTpContactList *list,
+ GList **contacts)
{
GList *l;
- l = empathy_contact_list_get_contacts (EMPATHY_CONTACT_LIST (list));
+ l = empathy_contact_list_get_local_pending (EMPATHY_CONTACT_LIST (list));
*contacts = g_list_concat (*contacts, l);
}
diff --git a/libempathy/empathy-idle.c b/libempathy/empathy-idle.c
index 6b9cfb3b9..f9b50bd40 100644
--- a/libempathy/empathy-idle.c
+++ b/libempathy/empathy-idle.c
@@ -27,8 +27,6 @@
#include <libtelepathy/tp-helpers.h>
-#include <libmissioncontrol/mission-control.h>
-
#include "empathy-idle.h"
#include "gossip-utils.h"
#include "gossip-debug.h"
@@ -49,6 +47,9 @@ struct _EmpathyIdlePriv {
MissionControl *mc;
DBusGProxy *gs_proxy;
gboolean is_idle;
+ McPresence state;
+ McPresence slack_state;
+ gchar *status;
McPresence saved_state;
gchar *saved_status;
guint ext_away_timeout;
@@ -57,6 +58,17 @@ struct _EmpathyIdlePriv {
static void empathy_idle_class_init (EmpathyIdleClass *klass);
static void empathy_idle_init (EmpathyIdle *idle);
static void idle_finalize (GObject *object);
+static void idle_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void idle_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void idle_presence_changed_cb (MissionControl *mc,
+ McPresence state,
+ EmpathyIdle *idle);
static void idle_session_idle_changed_cb (DBusGProxy *gs_proxy,
gboolean is_idle,
EmpathyIdle *idle);
@@ -64,7 +76,12 @@ static void idle_ext_away_start (EmpathyIdle *idle);
static void idle_ext_away_stop (EmpathyIdle *idle);
static gboolean idle_ext_away_cb (EmpathyIdle *idle);
-//static guint signals[LAST_SIGNAL];
+enum {
+ PROP_0,
+ PROP_STATE,
+ PROP_STATUS,
+ PROP_SLACK_STATE
+};
G_DEFINE_TYPE (EmpathyIdle, empathy_idle, G_TYPE_OBJECT)
@@ -74,6 +91,34 @@ empathy_idle_class_init (EmpathyIdleClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = idle_finalize;
+ object_class->get_property = idle_get_property;
+ object_class->set_property = idle_set_property;
+
+ g_object_class_install_property (object_class,
+ PROP_STATE,
+ g_param_spec_uint ("state",
+ "state",
+ "state",
+ MC_PRESENCE_UNSET,
+ LAST_MC_PRESENCE,
+ MC_PRESENCE_AVAILABLE,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_STATUS,
+ g_param_spec_string ("status",
+ "status",
+ "status",
+ NULL,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_SLACK_STATE,
+ g_param_spec_uint ("slack-state",
+ "slack-state",
+ "slack-state",
+ MC_PRESENCE_UNSET,
+ LAST_MC_PRESENCE,
+ MC_PRESENCE_UNSET,
+ G_PARAM_READWRITE));
g_type_class_add_private (object_class, sizeof (EmpathyIdlePriv));
}
@@ -87,6 +132,8 @@ empathy_idle_init (EmpathyIdle *idle)
priv->is_idle = FALSE;
priv->mc = gossip_mission_control_new ();
+ priv->state = mission_control_get_presence_actual (priv->mc, NULL);
+ priv->status = mission_control_get_presence_message_actual (priv->mc, NULL);
priv->gs_proxy = dbus_g_proxy_new_for_name (tp_get_bus (),
"org.gnome.ScreenSaver",
"/org/gnome/ScreenSaver",
@@ -102,6 +149,10 @@ empathy_idle_init (EmpathyIdle *idle)
dbus_g_proxy_connect_signal (priv->gs_proxy, "SessionIdleChanged",
G_CALLBACK (idle_session_idle_changed_cb),
idle, NULL);
+ dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->mc),
+ "PresenceStatusActual",
+ G_CALLBACK (idle_presence_changed_cb),
+ idle, NULL);
}
static void
@@ -111,6 +162,7 @@ idle_finalize (GObject *object)
priv = GET_PRIV (object);
+ g_free (priv->status);
g_free (priv->saved_status);
g_object_unref (priv->mc);
@@ -121,6 +173,62 @@ idle_finalize (GObject *object)
idle_ext_away_stop (EMPATHY_IDLE (object));
}
+static void
+idle_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EmpathyIdlePriv *priv;
+ EmpathyIdle *idle;
+
+ priv = GET_PRIV (object);
+ idle = EMPATHY_IDLE (object);
+
+ switch (param_id) {
+ case PROP_STATE:
+ g_value_set_uint (value, empathy_idle_get_state (idle));
+ break;
+ case PROP_STATUS:
+ g_value_set_string (value, empathy_idle_get_status (idle));
+ break;
+ case PROP_SLACK_STATE:
+ g_value_set_uint (value, empathy_idle_get_slack_state (idle));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ };
+}
+
+static void
+idle_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EmpathyIdlePriv *priv;
+ EmpathyIdle *idle;
+
+ priv = GET_PRIV (object);
+ idle = EMPATHY_IDLE (object);
+
+ switch (param_id) {
+ case PROP_STATE:
+ empathy_idle_set_state (idle, g_value_get_uint (value));
+ break;
+ case PROP_STATUS:
+ empathy_idle_set_status (idle, g_value_get_string (value));
+ break;
+ case PROP_SLACK_STATE:
+ empathy_idle_set_slack_state (idle, g_value_get_uint (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ };
+}
+
EmpathyIdle *
empathy_idle_new (void)
{
@@ -136,6 +244,99 @@ empathy_idle_new (void)
return idle;
}
+McPresence
+empathy_idle_get_state (EmpathyIdle *idle)
+{
+ EmpathyIdlePriv *priv;
+
+ priv = GET_PRIV (idle);
+
+ return priv->state;
+}
+
+void
+empathy_idle_set_state (EmpathyIdle *idle,
+ McPresence state)
+{
+ EmpathyIdlePriv *priv;
+
+ priv = GET_PRIV (idle);
+
+ mission_control_set_presence (priv->mc,
+ state,
+ priv->status,
+ NULL, NULL);
+}
+
+const gchar *
+empathy_idle_get_status (EmpathyIdle *idle)
+{
+ EmpathyIdlePriv *priv;
+
+ priv = GET_PRIV (idle);
+
+ return priv->status;
+}
+
+void
+empathy_idle_set_status (EmpathyIdle *idle,
+ const gchar *status)
+{
+ EmpathyIdlePriv *priv;
+
+ priv = GET_PRIV (idle);
+
+ mission_control_set_presence (priv->mc,
+ priv->state,
+ status,
+ NULL, NULL);
+}
+
+McPresence
+empathy_idle_get_slack_state (EmpathyIdle *idle)
+{
+ EmpathyIdlePriv *priv;
+
+ priv = GET_PRIV (idle);
+
+ return priv->slack_state;
+}
+
+void
+empathy_idle_set_slack_state (EmpathyIdle *idle,
+ McPresence state)
+{
+ EmpathyIdlePriv *priv;
+
+ priv = GET_PRIV (idle);
+
+ priv->slack_state = state;
+
+ g_object_notify (G_OBJECT (idle), "slack-state");
+}
+
+static void
+idle_presence_changed_cb (MissionControl *mc,
+ McPresence state,
+ EmpathyIdle *idle)
+{
+ EmpathyIdlePriv *priv;
+
+ priv = GET_PRIV (idle);
+
+ g_free (priv->status);
+ priv->state = state;
+ priv->status = mission_control_get_presence_message_actual (priv->mc, NULL);
+
+ if (G_STR_EMPTY (priv->status)) {
+ g_free (priv->status);
+ priv->status = g_strdup (gossip_presence_state_get_default_status (state));
+ }
+
+ g_object_notify (G_OBJECT (idle), "state");
+ g_object_notify (G_OBJECT (idle), "status");
+}
+
static void
idle_session_idle_changed_cb (DBusGProxy *gs_proxy,
gboolean is_idle,
@@ -150,30 +351,29 @@ idle_session_idle_changed_cb (DBusGProxy *gs_proxy,
is_idle ? "yes" : "no");
if (is_idle && !priv->is_idle) {
- McPresence new_state = MC_PRESENCE_AWAY;
+ McPresence new_state;
/* We are now idle, set state to away */
- priv->saved_state = mission_control_get_presence_actual (priv->mc, NULL);
- priv->saved_status = mission_control_get_presence_message_actual (priv->mc, NULL);
-
- if (priv->saved_state <= MC_PRESENCE_OFFLINE ||
- priv->saved_state == MC_PRESENCE_HIDDEN) {
+ if (priv->state <= MC_PRESENCE_OFFLINE ||
+ priv->state == MC_PRESENCE_HIDDEN) {
/* We are not online so nothing to do here */
return;
- } else if (priv->saved_state == MC_PRESENCE_AWAY ||
- priv->saved_state == MC_PRESENCE_EXTENDED_AWAY) {
+ } else if (priv->state == MC_PRESENCE_AWAY ||
+ priv->state == MC_PRESENCE_EXTENDED_AWAY) {
/* User set away manually, when coming back we restore
* default presence. */
- new_state = priv->saved_state;
+ new_state = priv->state;
priv->saved_state = MC_PRESENCE_AVAILABLE;
priv->saved_status = NULL;
+ } else {
+ new_state = MC_PRESENCE_AWAY;
+ priv->saved_state = priv->state;
+ priv->saved_status = g_strdup (priv->status);
}
gossip_debug (DEBUG_DOMAIN, "Going to autoaway");
- mission_control_set_presence (priv->mc,
- new_state,
- priv->saved_status,
- NULL, NULL);
+ empathy_idle_set_state (idle, new_state);
+
idle_ext_away_start (idle);
} else if (!is_idle && priv->is_idle) {
/* We are no more idle, restore state */
@@ -187,6 +387,7 @@ idle_session_idle_changed_cb (DBusGProxy *gs_proxy,
priv->saved_state,
priv->saved_status,
NULL, NULL);
+
g_free (priv->saved_status);
priv->saved_status = NULL;
}
diff --git a/libempathy/empathy-idle.h b/libempathy/empathy-idle.h
index df8846b9b..13c5dd293 100644
--- a/libempathy/empathy-idle.h
+++ b/libempathy/empathy-idle.h
@@ -25,6 +25,8 @@
#include <glib.h>
+#include <libmissioncontrol/mission-control.h>
+
G_BEGIN_DECLS
#define EMPATHY_TYPE_IDLE (empathy_idle_get_type ())
@@ -46,8 +48,17 @@ struct _EmpathyIdleClass {
GObjectClass parent_class;
};
-GType empathy_idle_get_type (void) G_GNUC_CONST;
-EmpathyIdle *empathy_idle_new (void);
+GType empathy_idle_get_type (void) G_GNUC_CONST;
+EmpathyIdle *empathy_idle_new (void);
+McPresence empathy_idle_get_state (EmpathyIdle *idle);
+void empathy_idle_set_state (EmpathyIdle *idle,
+ McPresence state);
+const gchar *empathy_idle_get_status (EmpathyIdle *idle);
+void empathy_idle_set_status (EmpathyIdle *idle,
+ const gchar *message);
+McPresence empathy_idle_get_slack_state (EmpathyIdle *idle);
+void empathy_idle_set_slack_state (EmpathyIdle *idle,
+ McPresence state);
G_END_DECLS
diff --git a/libempathy/empathy-marshal.list b/libempathy/empathy-marshal.list
index f13e9f08d..3b36b7be0 100644
--- a/libempathy/empathy-marshal.list
+++ b/libempathy/empathy-marshal.list
@@ -1,8 +1,10 @@
-VOID:POINTER,UINT,UINT,STRING
VOID:OBJECT,UINT
VOID:OBJECT,OBJECT
-VOID:INT,STRING
VOID:OBJECT,OBJECT,UINT
-VOID:UINT,BOOLEAN
VOID:OBJECT,BOOLEAN
VOID:OBJECT,STRING,STRING
+VOID:OBJECT,STRING
+VOID:POINTER,UINT,UINT,STRING
+VOID:INT,STRING
+VOID:UINT,BOOLEAN
+
diff --git a/libempathy/empathy-tp-chatroom.c b/libempathy/empathy-tp-chatroom.c
index eb47c9bb3..232db30fd 100644
--- a/libempathy/empathy-tp-chatroom.c
+++ b/libempathy/empathy-tp-chatroom.c
@@ -72,7 +72,7 @@ static void tp_chatroom_add (EmpathyContactList *
static void tp_chatroom_remove (EmpathyContactList *list,
GossipContact *contact,
const gchar *message);
-static GList * tp_chatroom_get_contacts (EmpathyContactList *list);
+static GList * tp_chatroom_get_members (EmpathyContactList *list);
G_DEFINE_TYPE_WITH_CODE (EmpathyTpChatroom, empathy_tp_chatroom, EMPATHY_TYPE_TP_CHAT,
G_IMPLEMENT_INTERFACE (EMPATHY_TYPE_CONTACT_LIST,
@@ -91,11 +91,11 @@ empathy_tp_chatroom_class_init (EmpathyTpChatroomClass *klass)
static void
tp_chatroom_iface_init (EmpathyContactListIface *iface)
{
- iface->setup = tp_chatroom_setup;
- iface->find = tp_chatroom_find;
- iface->add = tp_chatroom_add;
- iface->remove = tp_chatroom_remove;
- iface->get_contacts = tp_chatroom_get_contacts;
+ iface->setup = tp_chatroom_setup;
+ iface->find = tp_chatroom_find;
+ iface->add = tp_chatroom_add;
+ iface->remove = tp_chatroom_remove;
+ iface->get_members = tp_chatroom_get_members;
}
static void
@@ -339,7 +339,7 @@ tp_chatroom_remove (EmpathyContactList *list,
}
static GList *
-tp_chatroom_get_contacts (EmpathyContactList *list)
+tp_chatroom_get_members (EmpathyContactList *list)
{
EmpathyTpChatroomPriv *priv;
GArray *members;
diff --git a/libempathy/empathy-tp-contact-list.c b/libempathy/empathy-tp-contact-list.c
index 7668057e7..284f51138 100644
--- a/libempathy/empathy-tp-contact-list.c
+++ b/libempathy/empathy-tp-contact-list.c
@@ -52,12 +52,12 @@ struct _EmpathyTpContactListPriv {
GossipContact *user_contact;
gboolean setup;
- GossipTelepathyGroup *known;
GossipTelepathyGroup *publish;
GossipTelepathyGroup *subscribe;
GHashTable *groups;
GHashTable *contacts;
+ GList *local_pending;
DBusGProxy *aliasing_iface;
DBusGProxy *avatars_iface;
@@ -67,7 +67,6 @@ struct _EmpathyTpContactListPriv {
};
typedef enum {
- TP_CONTACT_LIST_TYPE_KNOWN,
TP_CONTACT_LIST_TYPE_PUBLISH,
TP_CONTACT_LIST_TYPE_SUBSCRIBE,
TP_CONTACT_LIST_TYPE_UNKNOWN,
@@ -103,7 +102,10 @@ static void tp_contact_list_add (EmpathyC
static void tp_contact_list_remove (EmpathyContactList *list,
GossipContact *contact,
const gchar *message);
-static GList * tp_contact_list_get_contacts (EmpathyContactList *list);
+static GList * tp_contact_list_get_members (EmpathyContactList *list);
+static GList * tp_contact_list_get_local_pending (EmpathyContactList *list);
+static void tp_contact_list_remove_local_pending (EmpathyTpContactList *list,
+ GossipContact *contact);
static void tp_contact_list_contact_removed_foreach (guint handle,
GossipContact *contact,
EmpathyTpContactList *list);
@@ -120,20 +122,20 @@ static void tp_contact_list_newchannel_cb (DBusGPro
gboolean suppress_handle,
EmpathyTpContactList *list);
static TpContactListType tp_contact_list_get_type (EmpathyTpContactList *list,
- TpChan *list_chan);
-static void tp_contact_list_contact_added_cb (GossipTelepathyGroup *group,
+ GossipTelepathyGroup *group);
+static void tp_contact_list_added_cb (GossipTelepathyGroup *group,
GArray *handles,
guint actor_handle,
guint reason,
const gchar *message,
EmpathyTpContactList *list);
-static void tp_contact_list_contact_removed_cb (GossipTelepathyGroup *group,
+static void tp_contact_list_removed_cb (GossipTelepathyGroup *group,
GArray *handles,
guint actor_handle,
guint reason,
const gchar *message,
EmpathyTpContactList *list);
-static void tp_contact_list_local_pending_cb (GossipTelepathyGroup *group,
+static void tp_contact_list_pending_cb (GossipTelepathyGroup *group,
GArray *handles,
guint actor_handle,
guint reason,
@@ -173,7 +175,7 @@ static void tp_contact_list_group_members_removed_cb (GossipTe
guint reason,
const gchar *message,
EmpathyTpContactList *list);
-static void tp_contact_list_get_contacts_foreach (guint handle,
+static void tp_contact_list_get_members_foreach (guint handle,
GossipContact *contact,
GList **contacts);
static void tp_contact_list_get_info (EmpathyTpContactList *list,
@@ -248,11 +250,12 @@ empathy_tp_contact_list_class_init (EmpathyTpContactListClass *klass)
static void
tp_contact_list_iface_init (EmpathyContactListIface *iface)
{
- iface->setup = tp_contact_list_setup;
- iface->find = tp_contact_list_find;
- iface->add = tp_contact_list_add;
- iface->remove = tp_contact_list_remove;
- iface->get_contacts = tp_contact_list_get_contacts;
+ iface->setup = tp_contact_list_setup;
+ iface->find = tp_contact_list_find;
+ iface->add = tp_contact_list_add;
+ iface->remove = tp_contact_list_remove;
+ iface->get_members = tp_contact_list_get_members;
+ iface->get_local_pending = tp_contact_list_get_local_pending;
}
static void
@@ -293,15 +296,9 @@ tp_contact_list_finalize (GObject *object)
if (priv->tp_conn) {
g_object_unref (priv->tp_conn);
}
-
- if (priv->known) {
- g_object_unref (priv->known);
- }
-
if (priv->subscribe) {
g_object_unref (priv->subscribe);
}
-
if (priv->publish) {
g_object_unref (priv->publish);
}
@@ -312,6 +309,9 @@ tp_contact_list_finalize (GObject *object)
g_hash_table_destroy (priv->groups);
g_hash_table_destroy (priv->contacts);
+ g_list_foreach (priv->local_pending, (GFunc) empathy_contact_list_info_free, NULL);
+ g_list_free (priv->local_pending);
+
G_OBJECT_CLASS (empathy_tp_contact_list_parent_class)->finalize (object);
}
@@ -383,6 +383,7 @@ empathy_tp_contact_list_new (McAccount *account)
error ? error->message : "No error given");
g_clear_error (&error);
} else {
+ /* FIXME: this adds the handle to the roster */
priv->user_contact = empathy_tp_contact_list_get_from_handle (list, handle);
}
@@ -490,11 +491,10 @@ tp_contact_list_remove (EmpathyContactList *list,
handle = gossip_contact_get_handle (contact);
gossip_telepathy_group_remove_member (priv->subscribe, handle, message);
gossip_telepathy_group_remove_member (priv->publish, handle, message);
- gossip_telepathy_group_remove_member (priv->known, handle, message);
}
static GList *
-tp_contact_list_get_contacts (EmpathyContactList *list)
+tp_contact_list_get_members (EmpathyContactList *list)
{
EmpathyTpContactListPriv *priv;
GList *contacts = NULL;
@@ -503,14 +503,25 @@ tp_contact_list_get_contacts (EmpathyContactList *list)
priv = GET_PRIV (list);
- /* FIXME: we should only return contacts that are in the contact list */
g_hash_table_foreach (priv->contacts,
- (GHFunc) tp_contact_list_get_contacts_foreach,
+ (GHFunc) tp_contact_list_get_members_foreach,
&contacts);
return contacts;
}
+static GList *
+tp_contact_list_get_local_pending (EmpathyContactList *list)
+{
+ EmpathyTpContactListPriv *priv;
+
+ g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list), NULL);
+
+ priv = GET_PRIV (list);
+
+ return g_list_copy (priv->local_pending);
+}
+
McAccount *
empathy_tp_contact_list_get_account (EmpathyTpContactList *list)
{
@@ -943,87 +954,77 @@ tp_contact_list_newchannel_cb (DBusGProxy *proxy,
if (handle_type == TP_HANDLE_TYPE_LIST) {
TpContactListType list_type;
- list_type = tp_contact_list_get_type (list, new_chan);
+ group = gossip_telepathy_group_new (new_chan, priv->tp_conn);
+
+ list_type = tp_contact_list_get_type (list, group);
if (list_type == TP_CONTACT_LIST_TYPE_UNKNOWN) {
- gossip_debug (DEBUG_DOMAIN, "Unknown contact list channel");
+ gossip_debug (DEBUG_DOMAIN,
+ "Type of contact list channel unknown: %s",
+ gossip_telepathy_group_get_name (group));
+
g_object_unref (new_chan);
+ g_object_unref (group);
return;
+ } else {
+ gossip_debug (DEBUG_DOMAIN,
+ "New contact list channel of type: %d",
+ list_type);
}
- gossip_debug (DEBUG_DOMAIN, "New contact list channel of type: %d",
- list_type);
+ g_signal_connect (group, "members-added",
+ G_CALLBACK (tp_contact_list_added_cb),
+ list);
+ g_signal_connect (group, "members-removed",
+ G_CALLBACK (tp_contact_list_removed_cb),
+ list);
- group = gossip_telepathy_group_new (new_chan, priv->tp_conn);
+ members = gossip_telepathy_group_get_members (group);
+ tp_contact_list_added_cb (group, members, 0,
+ TP_CHANNEL_GROUP_CHANGE_REASON_NONE,
+ NULL, list);
+ g_array_free (members, TRUE);
+
+ if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH) {
+ GList *pendings, *l;
- switch (list_type) {
- case TP_CONTACT_LIST_TYPE_KNOWN:
- if (priv->known) {
- g_object_unref (priv->known);
- }
- priv->known = group;
- break;
- case TP_CONTACT_LIST_TYPE_PUBLISH:
if (priv->publish) {
g_object_unref (priv->publish);
}
priv->publish = group;
- break;
- case TP_CONTACT_LIST_TYPE_SUBSCRIBE:
- if (priv->subscribe) {
- g_object_unref (priv->subscribe);
- }
- priv->subscribe = group;
- break;
- default:
- g_assert_not_reached ();
- }
-
- /* Connect and setup the new contact-list group */
- if (list_type == TP_CONTACT_LIST_TYPE_KNOWN ||
- list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE) {
- g_signal_connect (group, "members-added",
- G_CALLBACK (tp_contact_list_contact_added_cb),
- list);
- g_signal_connect (group, "members-removed",
- G_CALLBACK (tp_contact_list_contact_removed_cb),
- list);
-
- members = gossip_telepathy_group_get_members (group);
- tp_contact_list_contact_added_cb (group, members, 0,
- TP_CHANNEL_GROUP_CHANGE_REASON_NONE,
- NULL, list);
- g_array_free (members, TRUE);
- }
- if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH) {
- GList *members, *l;
- GArray *pending;
+ /* Makes no sense to be in remote-pending */
g_signal_connect (group, "local-pending",
- G_CALLBACK (tp_contact_list_local_pending_cb),
+ G_CALLBACK (tp_contact_list_pending_cb),
list);
- members = gossip_telepathy_group_get_local_pending_members_with_info (group);
- if (!members) {
- g_object_unref (new_chan);
- return;
+ pendings = gossip_telepathy_group_get_local_pending_members_with_info (group);
+ if (pendings) {
+ GArray *pending;
+
+ pending = g_array_sized_new (FALSE, FALSE, sizeof (guint), 1);
+ for (l = pendings; l; l = l->next) {
+ GossipTpGroupInfo *info;
+
+ info = l->data;
+
+ g_array_insert_val (pending, 0, info->member);
+ tp_contact_list_pending_cb (group, pending,
+ info->actor,
+ info->reason,
+ info->message,
+ list);
+ }
+ g_array_free (pending, TRUE);
+ gossip_telepathy_group_info_list_free (pendings);
}
-
- pending = g_array_sized_new (FALSE, FALSE, sizeof (guint), 1);
- for (l = members; l; l = l->next) {
- GossipTpGroupInfo *info;
-
- info = l->data;
-
- g_array_insert_val (pending, 0, info->member);
- tp_contact_list_local_pending_cb (group, pending,
- info->actor,
- info->reason,
- info->message,
- list);
+ }
+ else if (list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE) {
+ if (priv->subscribe) {
+ g_object_unref (priv->subscribe);
}
-
- gossip_telepathy_group_info_list_free (members);
- g_array_free (pending, TRUE);
+ priv->subscribe = group;
+ } else {
+ g_assert_not_reached ();
}
}
else if (handle_type == TP_HANDLE_TYPE_GROUP) {
@@ -1065,72 +1066,69 @@ tp_contact_list_newchannel_cb (DBusGProxy *proxy,
static TpContactListType
tp_contact_list_get_type (EmpathyTpContactList *list,
- TpChan *list_chan)
+ GossipTelepathyGroup *group)
{
EmpathyTpContactListPriv *priv;
- GArray *handles;
- gchar **handle_name;
TpContactListType list_type;
- GError *error = NULL;
+ const gchar *name;
priv = GET_PRIV (list);
- handles = g_array_new (FALSE, FALSE, sizeof (guint));
- g_array_append_val (handles, list_chan->handle);
-
- if (!tp_conn_inspect_handles (DBUS_G_PROXY (priv->tp_conn),
- TP_HANDLE_TYPE_LIST,
- handles,
- &handle_name,
- &error)) {
- gossip_debug (DEBUG_DOMAIN,
- "InspectHandle Error: %s",
- error ? error->message : "No error given");
- g_clear_error (&error);
- g_array_free (handles, TRUE);
- return TP_CONTACT_LIST_TYPE_UNKNOWN;
- }
-
- if (strcmp (*handle_name, "subscribe") == 0) {
+ name = gossip_telepathy_group_get_name (group);
+ if (strcmp (name, "subscribe") == 0) {
list_type = TP_CONTACT_LIST_TYPE_SUBSCRIBE;
- } else if (strcmp (*handle_name, "publish") == 0) {
+ } else if (strcmp (name, "publish") == 0) {
list_type = TP_CONTACT_LIST_TYPE_PUBLISH;
- } else if (strcmp (*handle_name, "known") == 0) {
- list_type = TP_CONTACT_LIST_TYPE_KNOWN;
} else {
list_type = TP_CONTACT_LIST_TYPE_UNKNOWN;
}
- g_strfreev (handle_name);
- g_array_free (handles, TRUE);
-
return list_type;
}
static void
-tp_contact_list_contact_added_cb (GossipTelepathyGroup *group,
- GArray *handles,
- guint actor_handle,
- guint reason,
- const gchar *message,
- EmpathyTpContactList *list)
+tp_contact_list_added_cb (GossipTelepathyGroup *group,
+ GArray *handles,
+ guint actor_handle,
+ guint reason,
+ const gchar *message,
+ EmpathyTpContactList *list)
{
EmpathyTpContactListPriv *priv;
GList *added_list, *l;
+ TpContactListType list_type;
priv = GET_PRIV (list);
- added_list = empathy_tp_contact_list_get_from_handles (list, handles);
+ list_type = tp_contact_list_get_type (list, group);
+ added_list = empathy_tp_contact_list_get_from_handles (list, handles);
for (l = added_list; l; l = l->next) {
- GossipContact *contact;
+ GossipContact *contact;
+ GossipSubscription subscription;
contact = GOSSIP_CONTACT (l->data);
+
+ gossip_debug (DEBUG_DOMAIN, "Contact '%s' added to list type %d",
+ gossip_contact_get_name (contact),
+ list_type);
+
+ subscription = gossip_contact_get_subscription (contact);
+ if (list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE) {
+ subscription |= GOSSIP_SUBSCRIPTION_FROM;
+ }
+ else if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH) {
+ subscription |= GOSSIP_SUBSCRIPTION_TO;
+ }
+
tp_contact_list_block_contact (list, contact);
- gossip_contact_set_subscription (contact, GOSSIP_SUBSCRIPTION_BOTH);
+ gossip_contact_set_subscription (contact, subscription);
tp_contact_list_unblock_contact (list, contact);
- g_signal_emit_by_name (list, "contact-added", contact);
+ if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH) {
+ tp_contact_list_remove_local_pending (list, contact);
+ g_signal_emit_by_name (list, "contact-added", contact);
+ }
g_object_unref (contact);
}
@@ -1139,31 +1137,48 @@ tp_contact_list_contact_added_cb (GossipTelepathyGroup *group,
}
static void
-tp_contact_list_contact_removed_cb (GossipTelepathyGroup *group,
- GArray *handles,
- guint actor_handle,
- guint reason,
- const gchar *message,
- EmpathyTpContactList *list)
+tp_contact_list_removed_cb (GossipTelepathyGroup *group,
+ GArray *handles,
+ guint actor_handle,
+ guint reason,
+ const gchar *message,
+ EmpathyTpContactList *list)
{
EmpathyTpContactListPriv *priv;
GList *removed_list, *l;
+ TpContactListType list_type;
priv = GET_PRIV (list);
- removed_list = empathy_tp_contact_list_get_from_handles (list, handles);
+ list_type = tp_contact_list_get_type (list, group);
+ removed_list = empathy_tp_contact_list_get_from_handles (list, handles);
for (l = removed_list; l; l = l->next) {
- GossipContact *contact;
- guint handle;
+ GossipContact *contact;
+ GossipSubscription subscription;
contact = GOSSIP_CONTACT (l->data);
- handle = gossip_contact_get_handle (contact);
- g_hash_table_remove (priv->contacts, GUINT_TO_POINTER (handle));
+ gossip_debug (DEBUG_DOMAIN, "Contact '%s' removed from list type %d",
+ gossip_contact_get_name (contact),
+ list_type);
+
+ subscription = gossip_contact_get_subscription (contact);
+ if (list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE) {
+ subscription &= !GOSSIP_SUBSCRIPTION_FROM;
+ }
+ else if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH) {
+ subscription &= !GOSSIP_SUBSCRIPTION_TO;
+ }
- g_signal_emit_by_name (list, "contact-removed", contact);
+ tp_contact_list_block_contact (list, contact);
+ gossip_contact_set_subscription (contact, subscription);
+ tp_contact_list_unblock_contact (list, contact);
+ if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH) {
+ tp_contact_list_remove_local_pending (list, contact);
+ g_signal_emit_by_name (list, "contact-removed", contact);
+ }
g_object_unref (contact);
}
@@ -1171,30 +1186,41 @@ tp_contact_list_contact_removed_cb (GossipTelepathyGroup *group,
}
static void
-tp_contact_list_local_pending_cb (GossipTelepathyGroup *group,
- GArray *handles,
- guint actor_handle,
- guint reason,
- const gchar *message,
- EmpathyTpContactList *list)
+tp_contact_list_pending_cb (GossipTelepathyGroup *group,
+ GArray *handles,
+ guint actor_handle,
+ guint reason,
+ const gchar *message,
+ EmpathyTpContactList *list)
{
EmpathyTpContactListPriv *priv;
GList *pending_list, *l;
+ TpContactListType list_type;
priv = GET_PRIV (list);
- pending_list = empathy_tp_contact_list_get_from_handles (list, handles);
+ list_type = tp_contact_list_get_type (list, group);
+ pending_list = empathy_tp_contact_list_get_from_handles (list, handles);
for (l = pending_list; l; l = l->next) {
GossipContact *contact;
contact = GOSSIP_CONTACT (l->data);
- /* FIXME: Is that the correct way ? */
- tp_contact_list_block_contact (list, contact);
- gossip_contact_set_subscription (contact, GOSSIP_SUBSCRIPTION_FROM);
- tp_contact_list_unblock_contact (list, contact);
- g_signal_emit_by_name (list, "contact-added", contact);
+ gossip_debug (DEBUG_DOMAIN, "Contact '%s' pending in list type %d",
+ gossip_contact_get_name (contact),
+ list_type);
+
+ if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH) {
+ EmpathyContactListInfo *info;
+
+ info = empathy_contact_list_info_new (contact, message);
+ priv->local_pending = g_list_prepend (priv->local_pending,
+ info);
+
+ g_signal_emit_by_name (list, "local-pending",
+ contact, message);
+ }
g_object_unref (contact);
}
@@ -1203,6 +1229,30 @@ tp_contact_list_local_pending_cb (GossipTelepathyGroup *group,
}
static void
+tp_contact_list_remove_local_pending (EmpathyTpContactList *list,
+ GossipContact *contact)
+{
+ EmpathyTpContactListPriv *priv;
+ GList *l;
+
+ priv = GET_PRIV (list);
+
+ for (l = priv->local_pending; l; l = l->next) {
+ EmpathyContactListInfo *info;
+
+ info = l->data;
+ if (gossip_contact_equal (contact, info->contact)) {
+ gossip_debug (DEBUG_DOMAIN, "Contact no more local-pending: %s",
+ gossip_contact_get_name (contact));
+
+ priv->local_pending = g_list_delete_link (priv->local_pending, l);
+ empathy_contact_list_info_free (info);
+ break;
+ }
+ }
+}
+
+static void
tp_contact_list_groups_updated_cb (GossipContact *contact,
GParamSpec *param,
EmpathyTpContactList *list)
@@ -1531,11 +1581,16 @@ tp_contact_list_group_members_removed_cb (GossipTelepathyGroup *group,
}
static void
-tp_contact_list_get_contacts_foreach (guint handle,
+tp_contact_list_get_members_foreach (guint handle,
GossipContact *contact,
GList **contacts)
{
- *contacts = g_list_append (*contacts, g_object_ref (contact));
+ GossipSubscription subscription;
+
+ subscription = gossip_contact_get_subscription (contact);
+ if (subscription & GOSSIP_SUBSCRIPTION_TO) {
+ *contacts = g_list_append (*contacts, g_object_ref (contact));
+ }
}
static void