soylent r298 - in branches/libsoylent-v0.5.0: . docs/reference/libsoylent libsoylent libsoylent/example



Author: svenp
Date: Mon Aug 18 18:39:42 2008
New Revision: 298
URL: http://svn.gnome.org/viewvc/soylent?rev=298&view=rev

Log:
merged libsoylent v0.5.0 branch with newest version from trunk

Added:
   branches/libsoylent-v0.5.0/libsoylent/TODO
      - copied unchanged from r297, /trunk/libsoylent/TODO
   branches/libsoylent-v0.5.0/libsoylent/example/example-live.c
      - copied unchanged from r297, /trunk/libsoylent/example/example-live.c
Modified:
   branches/libsoylent-v0.5.0/configure.ac
   branches/libsoylent-v0.5.0/docs/reference/libsoylent/libsoylent-docs.sgml
   branches/libsoylent-v0.5.0/docs/reference/libsoylent/libsoylent-sections.txt
   branches/libsoylent-v0.5.0/libsoylent/NEWS
   branches/libsoylent-v0.5.0/libsoylent/README
   branches/libsoylent-v0.5.0/libsoylent/example/Makefile.am
   branches/libsoylent-v0.5.0/libsoylent/example/example.c
   branches/libsoylent-v0.5.0/libsoylent/example/example.h
   branches/libsoylent-v0.5.0/libsoylent/sl-attribute-eds.c
   branches/libsoylent-v0.5.0/libsoylent/sl-attributes.c
   branches/libsoylent-v0.5.0/libsoylent/sl-book.c
   branches/libsoylent-v0.5.0/libsoylent/sl-book.h
   branches/libsoylent-v0.5.0/libsoylent/sl-entity-eds.c
   branches/libsoylent-v0.5.0/libsoylent/sl-entity-eds.h
   branches/libsoylent-v0.5.0/libsoylent/sl-person.c
   branches/libsoylent-v0.5.0/libsoylent/sl-person.h
   branches/libsoylent-v0.5.0/libsoylent/sl-priv-util.c
   branches/libsoylent-v0.5.0/libsoylent/sl-priv-util.h
   branches/libsoylent-v0.5.0/libsoylent/soylent.c
   branches/libsoylent-v0.5.0/libsoylent/soylent.h

Modified: branches/libsoylent-v0.5.0/configure.ac
==============================================================================
--- branches/libsoylent-v0.5.0/configure.ac	(original)
+++ branches/libsoylent-v0.5.0/configure.ac	Mon Aug 18 18:39:42 2008
@@ -7,7 +7,7 @@
 m4_define(soylent_major_minor, soylent_major_version.soylent_minor_version)
 
 m4_define(libsoylent_major_version, 0)
-m4_define(libsoylent_minor_version, 4)
+m4_define(libsoylent_minor_version, 5)
 m4_define(libsoylent_micro_version, 0)
 m4_define(libsoylent_version, libsoylent_major_version.libsoylent_minor_version.libsoylent_micro_version)
 
@@ -111,18 +111,24 @@
 		glib-2.0
 		gobject-2.0
 		libebook-1.2
+    libmissioncontrol
+    libempathy
 	])
 	
 	PKG_CHECK_MODULES(TEST,
 	[
 		glib-2.0
+    gobject-2.0
 		libebook-1.2
+    libempathy
 	])
 
   PKG_CHECK_MODULES(EXAMPLE,
   [
     glib-2.0
+    gobject-2.0
     libebook-1.2
+    libempathy
   ])
 	
 	AC_DEFINE(ENABLE_LIBSOYLENT, 1, [Build libsoylent])

Modified: branches/libsoylent-v0.5.0/docs/reference/libsoylent/libsoylent-docs.sgml
==============================================================================
--- branches/libsoylent-v0.5.0/docs/reference/libsoylent/libsoylent-docs.sgml	(original)
+++ branches/libsoylent-v0.5.0/docs/reference/libsoylent/libsoylent-docs.sgml	Mon Aug 18 18:39:42 2008
@@ -5,7 +5,7 @@
   <bookinfo>
     <title>libsoylent Reference Manual</title>
     <releaseinfo>
-      for libsoylent v0.4.0; the latest version of this documentation can be found on-line at
+      for libsoylent v0.5.0; the latest version of this documentation can be found on-line at
       <ulink role="online-location" url="http://kalterregen.de/libsoylent/index.html";>http://kalterregen.de/libsoylent</ulink>.
     </releaseinfo>
   </bookinfo>
@@ -21,10 +21,13 @@
     <title>libsoylent API Reference</title>
     <xi:include href="xml/soylent.xml"/>
     <xi:include href="xml/sl-book.xml"/>
-    <xi:include href="xml/sl-entity.xml"/>
+    <xi:include href="xml/sl-person.xml"/>
     <xi:include href="xml/sl-attribute.xml"/>
+    <xi:include href="xml/sl-attributes.xml"/>
     <xi:include href="xml/well-known-attributes.xml" />
-    <xi:include href="xml/sl-person.xml"/>
+    <xi:include href="xml/sl-attribute-types.xml"/>
+    <xi:include href="xml/sl-entity.xml"/>
+
     <!--<xi:include href="xml/sl-group.xml"/>
         <xi:include href="xml/sl-entity-handler.xml"/>
         <xi:include href="xml/sl-entity-handler-file.xml"/>

Modified: branches/libsoylent-v0.5.0/docs/reference/libsoylent/libsoylent-sections.txt
==============================================================================
--- branches/libsoylent-v0.5.0/docs/reference/libsoylent/libsoylent-sections.txt	(original)
+++ branches/libsoylent-v0.5.0/docs/reference/libsoylent/libsoylent-sections.txt	Mon Aug 18 18:39:42 2008
@@ -1,5 +1,8 @@
 <SECTION>
 <FILE>sl-person</FILE>
+<TITLE>SlPerson</TITLE>
+SL_PERSON_COMMUNICATION_CHAT_CB
+SlPersonCommunicateChatCb
 SL_PERSON_TYPE
 SlPerson
 SlPersonClass
@@ -31,6 +34,19 @@
 sl_person_set_full_name
 sl_person_set_name
 sl_person_set_nick
+sl_person_communicate_call
+sl_person_communicate_chat
+sl_person_communicate_chat_async
+sl_person_communicate_chat_from
+sl_person_communicate_chat_from_async
+sl_person_communicate_chat_to
+sl_person_communicate_chat_to_async
+sl_person_communicate_email
+sl_person_get_imcontacts
+sl_person_get_presence
+sl_person_get_string
+sl_person_has_iminfo
+sl_person_is_online
 <SUBSECTION Standard>
 SL_PERSON
 SL_IS_PERSON
@@ -42,6 +58,7 @@
 SlPersonPriv
 sl_person_new_with_econtact
 sl_person_constr_with_econtact
+sl_person_launch_chat
 </SECTION>
 
 <SECTION>
@@ -67,10 +84,6 @@
 SlEntity
 SlEntityClass
 sl_entity_constr
-sl_entity_constr_with_econtact
-sl_entity_set_ebook
-sl_entity_get_ebook
-sl_entity_get_econtact
 sl_entity_commit
 sl_entity_add_attribute
 sl_entity_remove_attribute
@@ -89,12 +102,24 @@
 sl_entity_has_attribute
 sl_entity_modified
 sl_entity_modified_at
+sl_entity_get_imcontacts
+sl_entity_get_presence
+sl_entity_has_iminfo
+sl_entity_is_online
 <SUBSECTION Private>
+sl_entity_constr_with_econtact
+sl_entity_get_econtact
 sl_entity_add_attribute_shallow
 sl_entity_get_attribute_create
 sl_entity_get_attribute_from_eattr
 sl_entity_remove_attribute_shallow
 sl_entity_set_econtact
+sl_entity_set_storage
+sl_entity_associate_imcontact
+sl_entity_associate_imcontacts
+sl_entity_deassociate_imcontact
+sl_entity_get_imcontact_from_account_id
+sl_entity_get_imcontact_from_id
 sl_is_ignored_eattr
 <SUBSECTION Standard>
 SL_ENTITY
@@ -122,6 +147,7 @@
 SlBookCBPersonAttributeRemoved
 SlBookCBPersonModified
 SlBookCBPersonRemoved
+SlBookPersonPresenceChangedCb
 sl_book_constr
 sl_book_get_books
 sl_book_exists
@@ -133,6 +159,8 @@
 sl_book_remove_person
 sl_book_get_people
 sl_book_get_person
+sl_book_get_online_people
+sl_book_commit_person
 <SUBSECTION Standard>
 SL_BOOK
 SL_IS_BOOK
@@ -149,12 +177,16 @@
 sl_book_emit_person_attribute_modified
 sl_book_emit_person_attribute_removed
 sl_book_emit_person_removed
+sl_book_emit_person_presence_changed
 </SECTION>
 
 <SECTION>
 <FILE>soylent</FILE>
+<TITLE>soylent</TITLE>
 sl_init
 sl_cleanup
+sl_im_get_contact_manager
+sl_im_is_im_attribute
 sl_marshal_VOID__OBJECT_BOOLEAN
 sl_marshal_VOID__OBJECT_OBJECT_BOOLEAN
 sl_marshal_VOID__OBJECT_OBJECT_POINTER_BOOLEAN
@@ -282,4 +314,11 @@
 SL_ATTR_PHOTO
 SL_ATTR_TELEPHONE
 SL_ATTR_URL
+SL_ATTR_AIM
+SL_ATTR_GADUGADU
+SL_ATTR_GROUPWISE
+SL_ATTR_ICQ
+SL_ATTR_JABBER
+SL_ATTR_MSN
+SL_ATTR_YAHOO
 </SECTION>

Modified: branches/libsoylent-v0.5.0/libsoylent/NEWS
==============================================================================
--- branches/libsoylent-v0.5.0/libsoylent/NEWS	(original)
+++ branches/libsoylent-v0.5.0/libsoylent/NEWS	Mon Aug 18 18:39:42 2008
@@ -1,3 +1,28 @@
+=== 2008.08.18: libsoylent v0.5.0 "let's talk about..." ===
+
+Version 0.5.0 brings online-functionality to libsoylent. Want to launch a chat
+with someone? One function call. Want to see who's online? One function call.
+Want to see someone's online-status? You get it.
+
+This release is also the last one for Google Summer of Code 2008. It's the
+result of about four months of work. Phew.
+
+The plan for the next release is that it will be a pure documentation and
+bug-fixing release. Also in that version: libsoylent will stop taking control
+of strings passed to it.
+
+--- Changes ---
+
+ * implemented Telepathy / Mission-Control / Empathy support
+ * implemented various functions / methods for IM-information (get
+   online-people, get presence etc.)
+ * added communication functions (e.g. launching a chat with someone)
+ * added an example for online-functionality
+ * enhanced documentation
+ * fixed some bugs
+
+--------------------------------------------------------------------------------
+
 === 2008.08.12: libsoylent v0.4.0 "small step, giant leap" ===
 
 Let me present you the newest version of libsoylent: 0.4.0. Three weeks of hard

Modified: branches/libsoylent-v0.5.0/libsoylent/README
==============================================================================
--- branches/libsoylent-v0.5.0/libsoylent/README	(original)
+++ branches/libsoylent-v0.5.0/libsoylent/README	Mon Aug 18 18:39:42 2008
@@ -11,8 +11,9 @@
 
 --- State ---
 
-v0.4.*: libsoylent is work-in-progress. Some minor features are missing, but
-the core-functionality is implemented. The library still needs some testing.
+v0.5.*: libsoylent is work-in-progress. Some minor features are missing, but
+the core-functionality is implemented. Focus now lies on testing and
+documentation.
 Even if it's unlikely that libsoylent will cause any damage you are encouraged
 (as with any work-in-progress software) to backup your system (or at least
 your ~/.evolution directory) before using libsoylent.
@@ -72,15 +73,19 @@
 
 --- Contact ---
 
-Bugs, feature requests, questions and related discussion go to the Soylent
+Feature requests, questions and related discussion go to the Soylent
 mailinglist. You can join at:
 
 http://lists.codethink.co.uk/cgi-bin/mailman/listinfo/soylent-devel
 
+If you found a bug please report it at:
+
+http://bugzilla.gnome.org/browse.cgi?product=soylent
+
 --- Known Bugs ---
 
 Note: because of bug 1 to 3, addressbook functionality has been disabled in
-v0.4.0, i.e. you can only use the default addressbook.
+v0.5.0, i.e. you can only use the default addressbook.
 
  * [1] if you have never started Evolution before there will be no system-
    addressbook, so all addressbook-functions will fail [TODO; workaround:

Modified: branches/libsoylent-v0.5.0/libsoylent/example/Makefile.am
==============================================================================
--- branches/libsoylent-v0.5.0/libsoylent/example/Makefile.am	(original)
+++ branches/libsoylent-v0.5.0/libsoylent/example/Makefile.am	Mon Aug 18 18:39:42 2008
@@ -8,7 +8,8 @@
   example-list.c \
   example-create-person.c \
   example-attribute-handlers.c \
-  example-watch-book.c
+  example-watch-book.c \
+  example-live.c
 
 example_CFLAGS = $(WARN_CFLAGS) $(EXAMPLE_CFLAGS)
 example_LDADD = $(top_builddir)/libsoylent/libsoylent.la $(EXAMPLE_LIBS)

Modified: branches/libsoylent-v0.5.0/libsoylent/example/example.c
==============================================================================
--- branches/libsoylent-v0.5.0/libsoylent/example/example.c	(original)
+++ branches/libsoylent-v0.5.0/libsoylent/example/example.c	Mon Aug 18 18:39:42 2008
@@ -44,9 +44,11 @@
 
   /*create_person ();*/
   
-  watch_book ();
+  /*watch_book ();*/
   
   /*attribute_handlers ();*/
   
+  live ();
+  
   return EXIT_SUCCESS;
 }

Modified: branches/libsoylent-v0.5.0/libsoylent/example/example.h
==============================================================================
--- branches/libsoylent-v0.5.0/libsoylent/example/example.h	(original)
+++ branches/libsoylent-v0.5.0/libsoylent/example/example.h	Mon Aug 18 18:39:42 2008
@@ -29,3 +29,4 @@
 void create_person (void);
 void watch_book (void);
 void attribute_handlers (void);
+void live (void);

Modified: branches/libsoylent-v0.5.0/libsoylent/sl-attribute-eds.c
==============================================================================
--- branches/libsoylent-v0.5.0/libsoylent/sl-attribute-eds.c	(original)
+++ branches/libsoylent-v0.5.0/libsoylent/sl-attribute-eds.c	Mon Aug 18 18:39:42 2008
@@ -21,9 +21,20 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+/**
+ * SECTION:sl-attribute
+ * @short_description: an attribute of a #SlEntity
+ * @stability: Unstable
+ * @include: sl-attribute.h
+ *
+ * #SlAttribute is an attribute that holds a list of values. Arbitrary values
+ * can be added, removed and modified.
+ */
+
 #include "sl-mutual-inclusion.h"
 #include "sl-priv-util.h"
 #include "sl-attributes.h"
+#include "soylent.h"
 
 struct _SlAttributePriv
 {
@@ -196,8 +207,6 @@
   const gchar *name = g_hash_table_lookup (eattrname_to_name_map, eattrname);
   if (name == NULL)
     {
-      
-      /* TODO: this leaks, cause name must be freed somehow */
       if (!g_str_has_prefix (eattrname, "X-"))
         {
           /* workaround for illegal vCard fields */
@@ -209,6 +218,7 @@
         }
       else
         {
+          /* FIXME: this leaks, cause name must be freed somehow */
           name = g_utf8_strdown (&eattrname[2], -1);
         }
     }
@@ -420,6 +430,16 @@
   self->priv->values = g_list_append (self->priv->values, value);
   self->priv->eattributes = g_list_append (self->priv->eattributes, eattr);
   
+  /* im stuff */
+  if (self->priv->entity != NULL)
+    {
+      if (sl_im_is_im_attribute (self->priv->name))
+        {
+          sl_entity_associate_imcontacts (self->priv->entity);
+        }
+    }
+  /* /im stuff */
+  
   if (emit)
     {
       sl_attribute_emit_modified (self);
@@ -470,6 +490,16 @@
       return FALSE;
     }
 
+  /* im stuff */
+  if (self->priv->entity != NULL)
+    {
+      if (sl_im_is_im_attribute (self->priv->name))
+        {
+          sl_entity_associate_imcontacts (self->priv->entity);
+        }
+    }
+  /* /im stuff */
+  
   sl_attribute_cleanup (self->priv->name, value_nth->data);
   value_nth->data = value;
   
@@ -494,6 +524,16 @@
   g_assert (eattr_nth != NULL);
   EVCardAttribute *eattr = eattr_nth->data;
   
+  /* im stuff */
+  if (self->priv->entity != NULL)
+    {
+      if (sl_im_is_im_attribute (self->priv->name))
+        {
+          sl_entity_associate_imcontacts (self->priv->entity);
+        }
+    }
+  /* /im stuff */
+  
   self->priv->values = g_list_remove (self->priv->values, value);
   sl_attribute_cleanup (self->priv->name, value);
   

Modified: branches/libsoylent-v0.5.0/libsoylent/sl-attributes.c
==============================================================================
--- branches/libsoylent-v0.5.0/libsoylent/sl-attributes.c	(original)
+++ branches/libsoylent-v0.5.0/libsoylent/sl-attributes.c	Mon Aug 18 18:39:42 2008
@@ -21,6 +21,16 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+/**
+ * SECTION:sl-attributes
+ * @short_description: a system where attributes can be registered and mapped to
+ * runtime-types
+ * @stability: Unstable
+ * @include: sl-attributes.h
+ *
+ * TODO: add description and an example in libsoylent/example
+ */
+
 #include "sl-attributes.h"
 #include "sl-priv-util.h"
 
@@ -191,7 +201,7 @@
     }
   if (to_string == NULL)
     {
-      return "-";
+      return NULL;
     }
   else
     {

Modified: branches/libsoylent-v0.5.0/libsoylent/sl-book.c
==============================================================================
--- branches/libsoylent-v0.5.0/libsoylent/sl-book.c	(original)
+++ branches/libsoylent-v0.5.0/libsoylent/sl-book.c	Mon Aug 18 18:39:42 2008
@@ -24,11 +24,10 @@
 /**
  * SECTION:sl-book
  * @short_description: the addressbook
- * @see_also: #SlEntity
  * @stability: Unstable
  * @include: sl-book.h
  *
- * SlBook is basically like a real-world addressbook, i.e. it is responsible
+ * #SlBook is basically like a real-world addressbook, i.e. it is responsible
  * for managing people (adding and removing them to / from the addressbook).
  * Searching for people is also possible. Furthermore SlBook contains utility
  * functions to create, open and delete addressbooks.
@@ -37,6 +36,11 @@
 #include "sl-mutual-inclusion.h"
 #include "sl-priv-util.h"
 #include "sl-marshal.h"
+#include "soylent.h"
+
+#include <libempathy/empathy-contact-manager.h>
+#include <libempathy/empathy-utils.h>
+#include <dbus/dbus-glib.h>
 
 /* private structs and fields */
 
@@ -70,6 +74,11 @@
 static void eview_sequence_complete (EBookView *eview, EBookViewStatus status, 
                                      SlBook *self);
 
+static void empathy_contact_list_members_changed (
+  EmpathyContactList *contactlist, EmpathyContact *contact,
+  EmpathyContact *actor, guint reason, gchar *message, gboolean is_member,
+  SlBook *self);
+
 GType
 sl_book_get_type (void)
 {
@@ -141,6 +150,7 @@
   g_signal_new ("person-attribute-added", SL_BOOK_TYPE, G_SIGNAL_RUN_LAST, 0, NULL, NULL, sl_marshal_VOID__OBJECT_OBJECT_BOOLEAN, G_TYPE_NONE, 3, SL_PERSON_TYPE, SL_ATTRIBUTE_TYPE, G_TYPE_BOOLEAN);
   g_signal_new ("person-attribute-removed", SL_BOOK_TYPE, G_SIGNAL_RUN_LAST, 0, NULL, NULL, sl_marshal_VOID__OBJECT_OBJECT_BOOLEAN, G_TYPE_NONE, 3, SL_PERSON_TYPE, SL_ATTRIBUTE_TYPE, G_TYPE_BOOLEAN);
   g_signal_new ("person-attribute-modified", SL_BOOK_TYPE, G_SIGNAL_RUN_LAST, 0, NULL, NULL, sl_marshal_VOID__OBJECT_OBJECT_POINTER_BOOLEAN, G_TYPE_NONE, 4, SL_PERSON_TYPE, SL_ATTRIBUTE_TYPE, G_TYPE_POINTER, G_TYPE_BOOLEAN);
+  g_signal_new ("person-presence-changed", SL_BOOK_TYPE, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, SL_PERSON_TYPE);
 }
 
 static void
@@ -192,7 +202,7 @@
 
 gboolean
 sl_book_setup (GError **error)
-{
+{ 
   sl_book_default = sl_book_open_default (error);
   if (sl_book_default == NULL)
     {
@@ -435,6 +445,18 @@
   e_book_view_start (self->priv->eview);
   g_main_loop_run (self->priv->view_wait_loop);
   
+  sl_debug_book ("associating loaded people with loaded IM-contacts%s", "");
+
+  GList *people_iter = self->priv->people;
+  for (; people_iter != NULL; people_iter = people_iter->next)
+    {
+      SlPerson *person = people_iter->data;
+      sl_entity_associate_imcontacts (SL_ENTITY (person));
+    }
+  
+  EmpathyContactManager *contactmgr = sl_im_get_contact_manager ();
+  g_signal_connect (contactmgr, "members-changed", G_CALLBACK (empathy_contact_list_members_changed), self);
+  
   return TRUE;
 }
 
@@ -481,7 +503,7 @@
       return FALSE;
     }
   
-  sl_entity_set_ebook (entity, self->priv->ebook);
+  sl_entity_set_storage (entity, self);
   
   self->priv->people = g_list_append (self->priv->people, person);
   
@@ -503,6 +525,13 @@
   return TRUE;
 }
 
+gboolean
+sl_book_commit_person (SlBook *self, SlPerson *person, GError **error)
+{
+  EContact *econtact = sl_entity_get_econtact (SL_ENTITY (person));
+  return e_book_commit_contact (self->priv->ebook, econtact, error);
+}
+
 GList *
 sl_book_get_people (SlBook *self)
 {
@@ -510,38 +539,56 @@
   return self->priv->people;
 }
 
-SlPerson *
-sl_book_get_person (SlBook *self, const gchar *attrname, gpointer value)
+/**
+ * sl_book_get_online_people:
+ * @self: a #SlBook
+ *
+ * Gets a list of all people from addressbook @self that are online.
+ *
+ * Returns: a #SlPerson list of online people. The list should be freed with
+ * g_list_free().
+ */
+GList *
+sl_book_get_online_people (SlBook *self)
 {
-  /* TODO: this works only for strings atm */
+  GList *online_people = NULL;
   GList *people = self->priv->people;
   for (; people != NULL; people = people->next)
     {
       SlPerson *person = people->data;
-      if (g_str_equal ((gchar *) value, (gchar *) sl_person_get (person, attrname)))
+      if (sl_entity_is_online (SL_ENTITY (person)))
         {
-          return person;
+          online_people = g_list_append (online_people, person);
         }
     }
-  
-  return NULL;
+  return online_people;
 }
 
-/*static SlPerson *
-sl_book_get_person_from_econtact (SlBook *self, EContact *econtact)
+SlPerson *
+sl_book_get_person (SlBook *self, const gchar *attrname, gpointer value)
 {
+  /* TODO: this works only for strings atm */
   GList *people = self->priv->people;
   for (; people != NULL; people = people->next)
     {
       SlPerson *person = people->data;
-      if (sl_entity_get_econtact (SL_ENTITY (person)) == econtact)
+      if (g_str_equal ((gchar *) value, (gchar *) sl_person_get (person, attrname)))
         {
           return person;
         }
     }
   
   return NULL;
-}*/
+}
+
+void
+sl_book_emit_person_presence_changed (SlBook *self, SlPerson *person)
+{
+  g_return_if_fail (self != NULL && SL_IS_BOOK (self));
+  g_return_if_fail (person != NULL && SL_IS_PERSON (person));
+
+  g_signal_emit_by_name (self, "person-presence-changed", person);
+}
 
 void
 sl_book_emit_person_added (SlBook *self, SlPerson *person, gboolean on_purpose)
@@ -596,10 +643,14 @@
     {
       EContact *econtact = econtacts->data;
       SlPerson *person = sl_person_new_with_econtact (econtact);
+      sl_entity_set_storage (SL_ENTITY (person), self);
       self->priv->people = g_list_append (self->priv->people, person);
-      
+
       if (self->priv->view_wait_loop == NULL)
         {
+          /* im stuff */
+          sl_entity_associate_imcontacts (SL_ENTITY (person));
+          
           sl_book_emit_person_added (self, person, FALSE);
         }
     }
@@ -715,67 +766,7 @@
       g_list_free (g_list_first (modified));
       sl_priv_util_eattribute_deep_list_free (eattributes);
       sl_priv_util_eattribute_deep_list_free (eattributes_old);
-      
-      /*
-      sl_priv_util_eattribute_list_print (eattributes, "eattributes");
-      
-      sl_debug_book ("examining %d eattribute(s)", g_list_length (eattributes));
-      for (; eattributes != NULL; eattributes = eattributes->next)
-        {
-          
-          
-          EVCardAttribute *eattr = eattributes->data;
-          const gchar *eattrname = e_vcard_attribute_get_name (eattr);
-          if (sl_is_ignored_eattr (eattrname))
-            {
-              sl_debug_book ("ignoring eattribute \"%s\"", eattrname);
-              continue;
-            }
-
-          EVCardAttribute *eattr_old = e_vcard_get_attribute (E_VCARD (econtact_old), eattrname);
-          
-          if (eattr_old == NULL)
-            {
-              sl_debug_book ("found new eattribute \"%s\"", eattrname);
-              SlAttribute *attr = sl_attribute_new_with_eattr (eattr);
-              sl_person_add_attribute (person, attr);
-              sl_book_emit_person_attribute_added (self, person, attr, FALSE);
-              g_object_unref (attr);
-            }
-          else
-            {
-              GList *evalues = e_vcard_attribute_get_values (eattr);
-              GList *evalues_old = e_vcard_attribute_get_values (eattr_old);
-              if (!sl_priv_util_lists_equal (evalues, evalues_old, g_str_equal))
-                {
-                  sl_debug_book ("found modified eattribute \"%s\"", eattrname);
-                  SlAttribute *attr = sl_entity_get_attribute_from_eattr (entity, eattr_old);
-                  g_assert (attr != NULL);
-                  GList *old_values = sl_attribute_get_all (attr);
-                  sl_attribute_set_all_from_eattr (attr, eattr);
-                  sl_book_emit_person_attribute_modified (self, person, attr, old_values, FALSE);
-                }
-              eattributes_old = g_list_remove (eattributes_old, eattr_old);
-            }
-        }
-      
-      for (; eattributes_old != NULL; eattributes_old = eattributes_old->next)
-        {
-          EVCardAttribute *eattr_old = eattributes_old->data;
-          const gchar *eattrname_old = e_vcard_attribute_get_name (eattr_old);
-          if (sl_is_ignored_eattr (eattrname_old))
-            {
-              sl_debug_book ("ignoring eattribute \"%s\"", eattrname_old);
-              continue;
-            }
-          sl_debug_book ("eattribute \"%s\" doesn't exist anymore", e_vcard_attribute_get_name (eattr_old));
-          SlAttribute *attr = sl_entity_get_attribute_from_eattr (entity, eattr_old);
-          g_assert (attr != NULL);
-          sl_book_emit_person_attribute_removed (self, person, attr, FALSE);
-        }
-      */
-      
-      
+     
       //g_object_unref (econtact_old);
     }
 }
@@ -814,3 +805,25 @@
       self->priv->view_wait_loop = NULL;
     }
 }
+
+static void
+empathy_contact_list_members_changed (EmpathyContactList *contactlist,
+  EmpathyContact *imcontact, EmpathyContact *actor, guint reason, gchar *message,
+  gboolean is_member, SlBook *self)
+{
+  /*g_debug (sl_priv_util_imcontact_to_string (imcontact));*/
+  
+  GList *people = self->priv->people;
+  for (; people != NULL; people = people->next)
+    {
+      SlPerson *person = people->data;
+      if (is_member)
+        {
+          sl_entity_associate_imcontact (SL_ENTITY (person), imcontact, TRUE);
+        }
+      else
+        {
+          sl_entity_deassociate_imcontact (SL_ENTITY (person), imcontact);
+        }
+    }
+}

Modified: branches/libsoylent-v0.5.0/libsoylent/sl-book.h
==============================================================================
--- branches/libsoylent-v0.5.0/libsoylent/sl-book.h	(original)
+++ branches/libsoylent-v0.5.0/libsoylent/sl-book.h	Mon Aug 18 18:39:42 2008
@@ -69,6 +69,8 @@
 typedef void (*SlEntityCBAttributeRemoved)  (SlEntity *entity, SlAttribute *attr, gboolean on_purpose, gpointer user_data);
 typedef void (*SlEntityCBAttributeModified) (SlEntity *entity, SlAttribute *attr, gboolean on_purpose, GList *old_values, gpointer user_data);
 
+typedef void (*SlBookPersonPresenceChangedCb) (SlBook *book, SlPerson *person, gpointer user_data);
+
 enum SlBookProperty
 {
   SL_BOOK_PROPERTY_EBOOK = 1
@@ -97,7 +99,6 @@
 
 GType sl_book_get_type (void);
 GQuark sl_book_error_quark (void);
-
 gboolean sl_book_setup (GError **error);
 
 gboolean sl_book_constr (SlBook *self, GError **error);
@@ -111,10 +112,13 @@
 
 gboolean sl_book_add_person (SlBook *self, SlPerson *person, GError **error);
 gboolean sl_book_remove_person (SlBook *self, SlPerson *person, GError **error);
+gboolean sl_book_commit_person (SlBook *self, SlPerson *person, GError **error);
 /* TODO: more to come, like searching for attributes */
 GList *sl_book_get_people (SlBook *self);
+GList *sl_book_get_online_people (SlBook *self);
 SlPerson *sl_book_get_person (SlBook *self, const gchar *attrname, gpointer value);
 
+void sl_book_emit_person_presence_changed (SlBook *self, SlPerson *person);
 void sl_book_emit_person_added (SlBook *self, SlPerson *person, gboolean on_purpose);
 void sl_book_emit_person_removed (SlBook *self, SlPerson *person, gboolean on_purpose);
 void sl_book_emit_person_attribute_added (SlBook *self, SlPerson *person, SlAttribute *attr, gboolean on_purpose);

Modified: branches/libsoylent-v0.5.0/libsoylent/sl-entity-eds.c
==============================================================================
--- branches/libsoylent-v0.5.0/libsoylent/sl-entity-eds.c	(original)
+++ branches/libsoylent-v0.5.0/libsoylent/sl-entity-eds.c	Mon Aug 18 18:39:42 2008
@@ -24,19 +24,32 @@
 /* TODO: will be splitted to SlEntity (interface), SlEntityBase (abstract-
  * base class), SlEntityEDS. for now this will be misused as SlEntityEDS */
 
+/**
+ * SECTION:sl-entity
+ * @short_description: a entity (holding attributes)
+ * @stability: Unstable
+ * @include: sl-entity.h
+ *
+ * #SlEntity is a storage for attributes (#SlAttribute). Attributes can be
+ * added, removed and modified.
+ */
+
 #include "sl-mutual-inclusion.h"
 #include "sl-priv-util.h"
 #include "soylent.h"
 
+#include <libempathy/empathy-contact.h>
+
 /* private structs and fields */
 
 struct _SlEntityPriv
 {
   SlBook *storage;
-  EBook *ebook;
   EContact *econtact;
+  GList *imcontacts;
   GList *attributes;
   GHashTable *attribute_table;
+  McPresence presence;
 };
 
 static GObjectClass *parent_class = NULL;
@@ -49,6 +62,10 @@
 static void sl_entity_get_property (SlEntity *self, guint property_id,
 	GValue *value, GParamSpec *pspec);
 
+static void sl_entity_mix_presences (SlEntity *self);
+static void empathy_contact_notify_presence (EmpathyContact *imcontact,
+                                             GParamSpec *pspec, SlEntity *self);
+
 GType
 sl_entity_get_type (void)
 {
@@ -142,19 +159,21 @@
 sl_entity_constr (SlEntity *self)
 {
   self->priv->storage = NULL;
-  self->priv->ebook = NULL;
   self->priv->econtact = e_contact_new ();
+  self->priv->imcontacts = NULL;
   self->priv->attribute_table = g_hash_table_new (g_str_hash, g_str_equal);
   self->priv->attributes = NULL;
+  self->priv->presence = MC_PRESENCE_UNSET;
 }
 
 void
 sl_entity_constr_with_econtact (SlEntity *self, EContact *econtact)
 {
   self->priv->storage = NULL;
-  self->priv->ebook = NULL;
+  self->priv->imcontacts = NULL;
   self->priv->attribute_table = g_hash_table_new (g_str_hash, g_str_equal);
   self->priv->attributes = NULL;
+  self->priv->presence = MC_PRESENCE_UNSET;
   self->priv->econtact = g_object_ref (econtact);
   
   sl_debug_entity ("creating entity from econtact%s", "");
@@ -199,28 +218,124 @@
   g_list_free (eattributes);
 }
 
+EContact
+*sl_entity_get_econtact (SlEntity *self)
+{
+  return self->priv->econtact;
+}
+
 void
-sl_entity_set_ebook (SlEntity *self, EBook *ebook)
+sl_entity_set_econtact (SlEntity *self, EContact *econtact)
 {
-  self->priv->ebook = ebook;
+  self->priv->econtact = g_object_ref (econtact);
 }
 
-EBook *
-sl_entity_get_ebook (SlEntity *self)
+void
+sl_entity_associate_imcontacts (SlEntity *self)
 {
-  return self->priv->ebook;
+  sl_debug_entity ("associating imcontacts%s", "");
+  g_list_free (self->priv->imcontacts);
+  self->priv->imcontacts = NULL;
+  EmpathyContactManager *contactmgr = sl_im_get_contact_manager ();
+  GList *imcontacts = empathy_contact_list_get_members (EMPATHY_CONTACT_LIST (contactmgr));
+  for (; imcontacts != NULL; imcontacts = imcontacts->next)
+    {
+      sl_entity_associate_imcontact (self, imcontacts->data, FALSE);
+    }
+  sl_entity_mix_presences (self);
 }
 
-EContact
-*sl_entity_get_econtact (SlEntity *self)
+void
+sl_entity_associate_imcontact (SlEntity *self, EmpathyContact *imcontact, gboolean mix_presences)
 {
-  return self->priv->econtact;
+  McAccount *account = empathy_contact_get_account (imcontact);
+  const gchar *protocol_name = sl_priv_util_get_protocol_name_from_account (account);
+  const gchar *imcontactid = empathy_contact_get_id (imcontact);
+  if (imcontactid == NULL)
+    {
+      /*g_warning ("id of imcontact \"%s\" is NULL", empathy_contact_get_name (imcontact));*/
+      return;
+    }
+  
+  GList *ids = sl_entity_get_all (self, protocol_name);
+  for (; ids != NULL; ids = ids->next)
+    {
+      gchar *id = ids->data;
+      if (g_str_equal (id, imcontactid))
+        {
+          self->priv->imcontacts = g_list_append (self->priv->imcontacts, imcontact);
+          g_signal_connect (imcontact, "notify::presence", G_CALLBACK (empathy_contact_notify_presence), self);
+          if (mix_presences)
+            {
+              sl_entity_mix_presences (self);
+            }
+        }
+    }
 }
 
 void
-sl_entity_set_econtact (SlEntity *self, EContact *econtact)
+sl_entity_deassociate_imcontact (SlEntity *self, EmpathyContact *imcontact)
 {
-  self->priv->econtact = g_object_ref (econtact);
+  if (g_list_index (self->priv->imcontacts, imcontact) != -1) 
+    {
+      sl_entity_associate_imcontacts (self);
+    }
+}
+
+gboolean sl_entity_has_iminfo (SlEntity *self)
+{
+  return (self->priv->imcontacts != NULL);
+}
+
+gboolean sl_entity_is_online (SlEntity *self)
+{
+  return (self->priv->presence != MC_PRESENCE_UNSET &&
+          self->priv->presence != MC_PRESENCE_OFFLINE &&
+          self->priv->presence != MC_PRESENCE_HIDDEN);
+}
+
+McPresence sl_entity_get_presence (SlEntity *self)
+{
+  return self->priv->presence;
+}
+
+GList *
+sl_entity_get_imcontacts (SlEntity *self)
+{
+  return self->priv->imcontacts;
+}
+
+EmpathyContact *
+sl_entity_get_imcontact_from_id (SlEntity *self, const gchar *id)
+{
+  GList *imcontacts = sl_entity_get_imcontacts (self);
+  for (; imcontacts != NULL; imcontacts = imcontacts->next)
+    {
+      EmpathyContact *imcontact = imcontacts->data;
+      const gchar *imcontact_id = empathy_contact_get_id (imcontact);
+      if (g_str_equal (id, imcontact_id))
+        {
+          return imcontact;
+        }
+    }
+  return NULL;
+}
+
+EmpathyContact *
+sl_entity_get_imcontact_from_account_id (SlEntity *self, const gchar *account_id)
+{
+  GList *imcontacts = sl_entity_get_imcontacts (self);
+  for (; imcontacts != NULL; imcontacts = imcontacts->next)
+    {
+      EmpathyContact *imcontact = imcontacts->data;
+      gchar *imcontact_account_id = sl_priv_util_get_account_id_from_imcontact (imcontact);
+      if (g_str_equal (account_id, imcontact_account_id))
+        {
+          return imcontact;
+        }
+    }
+  
+  return NULL;
 }
 
 SlBook *
@@ -229,15 +344,21 @@
   return self->priv->storage;
 }
 
+void
+sl_entity_set_storage (SlEntity *self, SlBook *storage)
+{
+  self->priv->storage = storage;
+}
+
 gboolean
 sl_entity_commit (SlEntity *self, GError **error)
 {
-  if (self->priv->ebook == NULL)
+  if (self->priv->storage == NULL)
     {
       /* TODO: return error */
       return FALSE;
     }
-  return e_book_commit_contact (self->priv->ebook, self->priv->econtact, error);
+  return sl_book_commit_person (self->priv->storage, SL_PERSON (self), error);
 }
 
 void
@@ -247,6 +368,13 @@
   self->priv->attributes = g_list_append (self->priv->attributes, g_object_ref (attr));
   g_hash_table_insert (self->priv->attribute_table, (const gpointer) sl_attribute_get_name (attr), g_object_ref (attr));
   sl_attribute_set_entity (attr, self);
+  
+  /* im stuff */
+  if (sl_im_is_im_attribute (sl_attribute_get_name (attr)))
+    {
+      sl_entity_associate_imcontacts (self);
+    }
+  /* /im stuff */
 }
 
 void
@@ -257,6 +385,13 @@
   sl_attribute_set_entity (attr, NULL);
   g_object_unref (attr);
   g_object_unref (attr);
+  
+  /* im stuff */
+  if (sl_im_is_im_attribute (sl_attribute_get_name (attr)))
+    {
+      sl_entity_associate_imcontacts (self);
+    }
+  /* /im stuff */
 }
 
 void
@@ -439,3 +574,79 @@
   g_return_val_if_fail (attr != NULL, FALSE);
   return sl_attribute_modified_at (attr, index);
 }
+
+static gint
+sl_priv_util_presence_to_gint (McPresence presence)
+{
+  switch (presence)
+    {
+      case MC_PRESENCE_UNSET:
+        return 1;
+      case MC_PRESENCE_OFFLINE:
+        return 2;
+      case MC_PRESENCE_HIDDEN:
+        return 3;
+      case MC_PRESENCE_EXTENDED_AWAY:
+        return 4;
+      case MC_PRESENCE_AWAY:
+        return 5;
+      case MC_PRESENCE_DO_NOT_DISTURB:
+        return 6;
+      case MC_PRESENCE_AVAILABLE:
+        return 7;
+      default:
+        g_assert_not_reached ();
+    }
+}
+
+static void
+sl_entity_mix_presences (SlEntity *self)
+{
+  g_return_if_fail (self != NULL && SL_IS_PERSON (self));
+  
+  GList *imcontacts_iter = self->priv->imcontacts;
+  EmpathyContact *imcontact = NULL;
+  McPresence old_presence = self->priv->presence;
+
+  if (imcontacts_iter == NULL)
+    {
+      self->priv->presence = MC_PRESENCE_UNSET;
+    }
+  else
+    {
+      imcontact = imcontacts_iter->data;
+      imcontacts_iter = imcontacts_iter->next;
+      self->priv->presence = empathy_contact_get_presence (imcontact);
+    }
+
+  for (; imcontacts_iter != NULL; imcontacts_iter = imcontacts_iter->next)
+    {
+      McPresence presence = MC_PRESENCE_UNSET;
+      
+      imcontact = imcontacts_iter->data;
+      presence = empathy_contact_get_presence (imcontact);
+      if (sl_priv_util_presence_to_gint (presence) >
+          sl_priv_util_presence_to_gint (self->priv->presence))
+        {
+          self->priv->presence = presence;
+        }
+    }
+
+  if (old_presence != self->priv->presence)
+    {
+      sl_debug_entity ("presence %d -> %d", sl_priv_util_presence_to_gint (old_presence),
+                       sl_priv_util_presence_to_gint (self->priv->presence));
+      if (self->priv->storage != NULL)
+        {
+          sl_book_emit_person_presence_changed (self->priv->storage, SL_PERSON (self));
+        }
+    }
+}
+
+static void
+empathy_contact_notify_presence (EmpathyContact *imcontact, GParamSpec *pspec,
+                                 SlEntity *self)
+{
+  /* TODO: on account deactivate + active again we get this 3 times, why? */
+  sl_entity_mix_presences (self);
+}

Modified: branches/libsoylent-v0.5.0/libsoylent/sl-entity-eds.h
==============================================================================
--- branches/libsoylent-v0.5.0/libsoylent/sl-entity-eds.h	(original)
+++ branches/libsoylent-v0.5.0/libsoylent/sl-entity-eds.h	Mon Aug 18 18:39:42 2008
@@ -32,6 +32,7 @@
 #include <glib.h>
 #include <glib-object.h>
 #include <libebook/e-book.h>
+#include <libempathy/empathy-contact.h>
 
 #define SL_ENTITY_TYPE			 	    (sl_entity_get_type ())
 #define SL_ENTITY(obj)				    (G_TYPE_CHECK_INSTANCE_CAST (obj, \
@@ -73,15 +74,25 @@
 /*SlEntityHandler *sl_entity_get_handler (SlEntity *self);*/
 void sl_entity_constr (SlEntity *self);
 void sl_entity_constr_with_econtact (SlEntity *self, EContact *econtact);
-void sl_entity_set_ebook (SlEntity *self, EBook *ebook);
-EBook *sl_entity_get_ebook (SlEntity *self);
 EContact *sl_entity_get_econtact (SlEntity *self);
 void sl_entity_set_econtact (SlEntity *self, EContact *econtact);
 
+void sl_entity_associate_imcontacts (SlEntity *self);
+void sl_entity_associate_imcontact (SlEntity *self, EmpathyContact *imcontact, gboolean mix_presences);
+void sl_entity_deassociate_imcontact (SlEntity *self, EmpathyContact *imcontact);
+
 SlBook *sl_entity_get_storage (SlEntity *self);
+void sl_entity_set_storage (SlEntity *self, SlBook *storage);
 
 gboolean sl_entity_commit (SlEntity *self, GError **error);
 
+gboolean sl_entity_has_iminfo (SlEntity *self);
+gboolean sl_entity_is_online (SlEntity *self);
+McPresence sl_entity_get_presence (SlEntity *self);
+GList *sl_entity_get_imcontacts (SlEntity *self);
+EmpathyContact *sl_entity_get_imcontact_from_id (SlEntity *self, const gchar *id);
+EmpathyContact *sl_entity_get_imcontact_from_account_id (SlEntity *self, const gchar *account_id);
+
 void sl_entity_add_attribute_shallow (SlEntity *self, SlAttribute *attr);
 void sl_entity_remove_attribute_shallow (SlEntity *self, SlAttribute *attr);
 

Modified: branches/libsoylent-v0.5.0/libsoylent/sl-person.c
==============================================================================
--- branches/libsoylent-v0.5.0/libsoylent/sl-person.c	(original)
+++ branches/libsoylent-v0.5.0/libsoylent/sl-person.c	Mon Aug 18 18:39:42 2008
@@ -21,12 +21,47 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+/**
+ * SECTION:sl-person
+ * @short_description: a person
+ * @stability: Unstable
+ * @include: sl-person.h
+ *
+ * #SlPerson represents a real-world person. A person has attributes
+ * (#SlAttribute) that can be added, removed and modified.
+ */
+
+/**
+ * SECTION:well-known-attributes
+ * @short_description: descriptions of all well-known attributes
+ * @stability: Unstable
+ * @include: sl-person.h
+ *
+ * A well-known attribute is an attribute that's name is known to the system
+ * (e.g. nick, email). Every attribute has a description and a runtime-type.
+ */
+
+/**
+ * SECTION:sl-attribute-types
+ * @short_description: runtime-types of attribute-values
+ * @stability: Unstable
+ * @include: sl-person.h
+ *
+ * Some structs to make your life with attributes easier.
+ */
+
 #include "sl-mutual-inclusion.h"
 
+#include <libempathy/empathy-utils.h>
+
 /* private structs and fields */
 
 struct _SlPersonPriv
 {
+  gpointer cb_user_data;
+  GCallback cb;
+  GMainLoop *sync_loop;
+  GError *sync_error;
 };
 
 static GObjectClass *parent_class = NULL;
@@ -39,6 +74,8 @@
 static void sl_person_set_property (GObject *object, guint property_id,
   const GValue *value, GParamSpec *pspec);
 
+static void mc_chat_ready (MissionControl *mc, GError *error, SlPerson *self);
+
 GType
 sl_person_get_type (void)
 {
@@ -153,6 +190,8 @@
 sl_person_constr (SlPerson *self, const gchar *name, const gchar *family_name)
 {
   sl_entity_constr (SL_ENTITY (self));
+  self->priv->sync_loop = NULL;
+  self->priv->sync_error = NULL;
   SlName *n = sl_name_new ();
   n->names = g_list_append (NULL, (gchar *) name);
   n->family_name = (gchar *) family_name;
@@ -163,6 +202,8 @@
 sl_person_constr_with_econtact (SlPerson *self, EContact *econtact)
 {
   sl_entity_constr_with_econtact (SL_ENTITY (self), econtact);
+  self->priv->sync_loop = NULL;
+  self->priv->sync_error = NULL;
 }
 
 gchar *
@@ -228,3 +269,168 @@
 {
   sl_person_set (self, SL_ATTR_NICK, nick);
 }
+
+gchar *
+sl_person_get_string (SlPerson *self)
+{
+  gchar *nick = sl_person_get_nick (self);
+  if (nick == NULL || g_str_equal (nick, ""))
+    {
+      return "?";
+    }
+  return nick;
+}
+
+static void
+sl_async_init (GCallback *cbp, gpointer *cb_user_datap, GCallback cb, gpointer cb_user_data)
+{
+  g_return_if_fail (cbp != NULL);
+  g_return_if_fail (cb_user_datap != NULL);
+  
+  *cbp = cb;
+  *cb_user_datap = cb_user_data;
+}
+
+static void
+sl_sync_ready (GMainLoop **loopp, GError **errorp, GError *error)
+{
+  g_return_if_fail (loopp != NULL);
+  g_return_if_fail (errorp != NULL);
+  
+  *errorp = error;
+  g_main_loop_quit (*loopp);
+}
+
+static gboolean
+sl_synchronize (GMainLoop **loopp, GError **errorp, GError **error)
+{
+  g_return_val_if_fail (loopp != NULL, FALSE);
+  g_return_val_if_fail (errorp != NULL, FALSE);
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+  
+  *loopp = g_main_loop_new (NULL, FALSE);
+  g_main_loop_run (*loopp);
+  *loopp = NULL;
+  if (*errorp == NULL)
+    {
+      return TRUE;
+    }
+  else
+    {
+      g_propagate_error (error, *errorp);
+      *errorp = NULL;
+      return FALSE;
+    }
+}
+
+static void
+communicate_chat_sync_cb (SlPerson *person, GError *error, gpointer user_data)
+{
+  g_return_if_fail (person != NULL && SL_IS_PERSON (person));
+  
+  sl_sync_ready (&person->priv->sync_loop, &person->priv->sync_error, error);
+}
+
+gboolean
+sl_person_communicate_chat (SlPerson *self, GError **error)
+{
+  g_return_val_if_fail (self != NULL && SL_IS_PERSON (self), FALSE);
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+  
+  sl_person_communicate_chat_async (self, communicate_chat_sync_cb, NULL);
+  return sl_synchronize (&self->priv->sync_loop, &self->priv->sync_error, error);
+}
+
+void
+sl_person_communicate_chat_async (SlPerson *self, SlPersonCommunicateChatCb callback, gpointer user_data)
+{
+  g_return_if_fail (self != NULL && SL_IS_PERSON (self));
+  
+  /* TODO: better algorithm for finding "default" account to use for chat */
+  sl_async_init (&self->priv->cb, &self->priv->cb_user_data, G_CALLBACK (callback), user_data);
+  EmpathyContact *imcontact = sl_entity_get_imcontacts (SL_ENTITY (self))->data;
+  sl_person_launch_chat (self, imcontact);
+}
+
+gboolean
+sl_person_communicate_chat_to (SlPerson *self, const gchar *to_id, GError **error)
+{
+  g_return_val_if_fail (self != NULL && SL_IS_PERSON (self), FALSE);
+  g_return_val_if_fail (to_id != NULL, FALSE);
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+  
+  sl_person_communicate_chat_to_async (self, to_id, communicate_chat_sync_cb, NULL);
+  return sl_synchronize (&self->priv->sync_loop, &self->priv->sync_error, error);
+}
+
+void
+sl_person_communicate_chat_to_async (SlPerson *self, const gchar *to_id, SlPersonCommunicateChatCb callback, gpointer user_data)
+{
+  g_return_if_fail (self != NULL && SL_IS_PERSON (self));
+  g_return_if_fail (to_id != NULL);
+  
+  sl_async_init (&self->priv->cb, &self->priv->cb_user_data, G_CALLBACK (callback), user_data);
+  EmpathyContact *imcontact = sl_entity_get_imcontact_from_id (SL_ENTITY (self), to_id);
+  sl_person_launch_chat (self, imcontact);
+}
+
+gboolean
+sl_person_communicate_chat_from (SlPerson *self, const gchar *from_id, GError **error)
+{
+  g_return_val_if_fail (self != NULL && SL_IS_PERSON (self), FALSE);
+  g_return_val_if_fail (from_id != NULL, FALSE);
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+  
+  sl_person_communicate_chat_from_async (self, from_id, communicate_chat_sync_cb, NULL);
+  return sl_synchronize (&self->priv->sync_loop, &self->priv->sync_error, error);
+}
+
+void
+sl_person_communicate_chat_from_async (SlPerson *self, const gchar *from_id, SlPersonCommunicateChatCb callback, gpointer user_data)
+{
+  g_return_if_fail (self != NULL && SL_IS_PERSON (self));
+  g_return_if_fail (from_id != NULL);
+  
+  sl_async_init (&self->priv->cb, &self->priv->cb_user_data, G_CALLBACK (callback), user_data);
+  EmpathyContact *imcontact = sl_entity_get_imcontact_from_account_id (SL_ENTITY (self), from_id);
+  sl_person_launch_chat (self, imcontact);
+}
+
+void
+sl_person_launch_chat (SlPerson *self, EmpathyContact *imcontact)
+{
+  g_return_if_fail (self != NULL && SL_IS_PERSON (self));
+  g_return_if_fail (imcontact != NULL && EMPATHY_IS_CONTACT (imcontact));
+  
+  const gchar *id = empathy_contact_get_id (imcontact);
+  McAccount *account = empathy_contact_get_account (imcontact);
+  MissionControl *mc = empathy_mission_control_new ();
+  mission_control_request_channel_with_string_handle (mc, account,
+    TP_IFACE_CHANNEL_TYPE_TEXT, id, TP_HANDLE_TYPE_CONTACT, (McCallback) mc_chat_ready,
+    self);
+
+}
+
+gboolean
+sl_person_communicate_call (SlPerson *self, SlCall call_type, GError **error)
+{
+  g_warning ("%s not yet implemented", __FUNCTION__);
+  return FALSE;
+}
+
+gboolean
+sl_person_communicate_email (SlPerson *self, GError **error)
+{
+  g_warning ("%s not yet implemented", __FUNCTION__);
+  return FALSE;
+}
+
+static void
+mc_chat_ready (MissionControl *mc, GError *error, SlPerson *self)
+{
+  if (self->priv->cb != NULL)
+    {
+      SlPersonCommunicateChatCb cb = SL_PERSON_COMMUNICATION_CHAT_CB (self->priv->cb);
+      cb (self, error, self->priv->cb_user_data);
+    }
+}

Modified: branches/libsoylent-v0.5.0/libsoylent/sl-person.h
==============================================================================
--- branches/libsoylent-v0.5.0/libsoylent/sl-person.h	(original)
+++ branches/libsoylent-v0.5.0/libsoylent/sl-person.h	Mon Aug 18 18:39:42 2008
@@ -193,13 +193,68 @@
 #define SL_ATTR_JOB_ROLE      "job-role"
 #define SL_ATTR_JOB_TITLE     "job-title"
 
-/*#define EVC_X_AIM              "X-AIM"
-#define EVC_X_GADUGADU        "X-GADUGADU"
-#define EVC_X_ICQ              "X-ICQ"
-#define EVC_X_JABBER           "X-JABBER"
-#define EVC_X_MSN           	"X-MSN"
-#define EVC_X_YAHOO         	"X-YAHOO"
-#define EVC_X_GROUPWISE     	"X-GROUPWISE"*/
+/**
+ * SL_ATTR_AIM:
+ *
+ * An AIM-id of a person.
+ *
+ * type: <type>string</type>
+ */
+#define SL_ATTR_AIM "aim"
+
+/**
+ * SL_ATTR_GADUGADU:
+ *
+ * A GaduGadu-id of a person.
+ *
+ * type: <type>string</type>
+ */
+#define SL_ATTR_GADUGADU "gadugadu"
+
+/**
+ * SL_ATTR_ICQ:
+ *
+ * An ICQ-id of a person.
+ *
+ * type: <type>string</type>
+ */
+#define SL_ATTR_ICQ "icq"
+
+/**
+ * SL_ATTR_JABBER:
+ *
+ * A Jabber-id of a person.
+ *
+ * type: <type>string</type>
+ */
+#define SL_ATTR_JABBER "jabber"
+
+/**
+ * SL_ATTR_MSN:
+ *
+ * A MSN-id of a person.
+ *
+ * type: <type>string</type>
+ */
+#define SL_ATTR_MSN "msn"
+
+/**
+ * SL_ATTR_YAHOO:
+ *
+ * A Yahoo-id of a person.
+ *
+ * type: <type>string</type>
+ */
+#define SL_ATTR_YAHOO "yahoo"
+
+/**
+ * SL_ATTR_GROUPWISE:
+ *
+ * A Groupwise-id of a person.
+ *
+ * type: <type>string</type>
+ */
+#define SL_ATTR_GROUPWISE "groupwise"
 
 /*#define EVC_GEO		    "GEO"*/
 /*#define EVC_ICSCALENDAR     "ICSCALENDAR"*/
@@ -285,12 +340,34 @@
 #define sl_person_modified_at(self, attrname, index) \
   (sl_entity_modified_at (SL_ENTITY (self), attrname, index))
 
+#define sl_person_has_iminfo(self) \
+  (sl_entity_has_iminfo (SL_ENTITY (self)))
+#define sl_person_is_online(self) \
+  (sl_entity_is_online (SL_ENTITY (self)))
+#define sl_person_get_presence(self) \
+  (sl_entity_get_presence (SL_ENTITY (self)))
+#define sl_person_get_imcontacts(self) \
+  (sl_entity_get_imcontacts (SL_ENTITY (self)))
+
+#define SL_PERSON_COMMUNICATION_CHAT_CB(cb) ((SlPersonCommunicateChatCb) cb)
+
+typedef void (*SlPersonCommunicateChatCb) (SlPerson *person, GError *error,
+                                               gpointer user_data);
+
 typedef struct _SlPersonClass SlPersonClass;
 typedef struct _SlPersonPriv  SlPersonPriv;
   
 typedef struct _SlAddress SlAddress;
 typedef struct _SlName    SlName;
+  
+typedef enum _SlCall SlCall;
 
+enum _SlCall
+{
+  SL_CALL_AUDIO = 1,
+  SL_CALL_VIDEO
+};
+  
 struct _SlPerson
 {
   SlEntity parent;
@@ -350,4 +427,17 @@
 gchar *sl_person_get_nick (SlPerson *self);
 void sl_person_set_nick (SlPerson *self, gchar *nick);
 
+gchar *sl_person_get_string (SlPerson *self);
+
+gboolean sl_person_communicate_chat (SlPerson *self, GError **error);
+gboolean sl_person_communicate_chat_to (SlPerson *self, const gchar *to_id, GError **error);
+gboolean sl_person_communicate_chat_from (SlPerson *self, const gchar *from_id, GError **error);
+void sl_person_communicate_chat_async (SlPerson *self, SlPersonCommunicateChatCb callback, gpointer user_data);
+void sl_person_communicate_chat_to_async (SlPerson *self, const gchar *to_id, SlPersonCommunicateChatCb callback, gpointer user_data);
+void sl_person_communicate_chat_from_async (SlPerson *self, const gchar *from_id, SlPersonCommunicateChatCb callback, gpointer user_data);
+void sl_person_launch_chat (SlPerson *self, EmpathyContact *imcontact);
+
+gboolean sl_person_communicate_call (SlPerson *self, SlCall call_type, GError **error);
+gboolean sl_person_communicate_email (SlPerson *self, GError **error);
+
 #endif

Modified: branches/libsoylent-v0.5.0/libsoylent/sl-priv-util.c
==============================================================================
--- branches/libsoylent-v0.5.0/libsoylent/sl-priv-util.c	(original)
+++ branches/libsoylent-v0.5.0/libsoylent/sl-priv-util.c	Mon Aug 18 18:39:42 2008
@@ -94,15 +94,35 @@
   return (g_list_find_custom (list, data, sl_priv_util_compare_by_equal) != NULL);
 }
 
+gchar *
+sl_priv_util_imcontact_to_string (EmpathyContact *imcontact)
+{
+  g_return_val_if_fail (imcontact != NULL && EMPATHY_IS_CONTACT (imcontact), NULL);
+  
+  GString *gstr = g_string_new ("");
+  g_string_printf (gstr, "EmpathyContact [%s, %s]",
+    empathy_contact_get_name (imcontact), empathy_contact_get_id (imcontact));
+  gchar *str = gstr->str;
+  g_string_free (gstr, FALSE);
+  return str;
+}
+
 void
-sl_priv_util_list_print (GList *list, const gchar *title)
+sl_priv_util_list_print (GList *list, const gchar *title, SlPrivUtilToStringFunc to_string)
 {
   g_return_if_fail (title != NULL);
   
   g_print ("%s (%d):\n", title, g_list_length (list));
   for (; list != NULL; list = list->next)
     {
-      g_print (" * %s\n", (gchar *) list->data);
+      if (to_string == NULL)
+        {
+          g_print (" * %s\n", (gchar *) list->data);
+        }
+      else
+        {
+          g_print (" * %s\n", to_string (list->data));
+        }
     }
 }
 
@@ -156,7 +176,7 @@
   g_return_if_fail (table != NULL && title != NULL);
   
   GList *keys = g_hash_table_get_keys (table);
-  sl_priv_util_list_print (keys, title);
+  sl_priv_util_list_print (keys, title, NULL);
   g_list_free (keys);
 }
 
@@ -423,3 +443,23 @@
   *strvp = NULL;
   return strv;
 }
+
+gchar *
+sl_priv_util_get_account_id_from_imcontact (EmpathyContact *imcontact)
+{
+  McAccount *account = empathy_contact_get_account (imcontact);
+  gchar *id = NULL;
+  if (mc_account_get_param_string (account, "account", &id) == MC_ACCOUNT_SETTING_ABSENT)
+    {
+      g_critical ("failed to get account-id");
+    }
+  return id;
+}
+
+const gchar *
+sl_priv_util_get_protocol_name_from_account (McAccount *account)
+{
+  McProfile *profile = mc_account_get_profile (account);
+  McProtocol *protocol = mc_profile_get_protocol (profile);
+  return mc_protocol_get_name (protocol);
+}

Modified: branches/libsoylent-v0.5.0/libsoylent/sl-priv-util.h
==============================================================================
--- branches/libsoylent-v0.5.0/libsoylent/sl-priv-util.h	(original)
+++ branches/libsoylent-v0.5.0/libsoylent/sl-priv-util.h	Mon Aug 18 18:39:42 2008
@@ -25,6 +25,7 @@
 #define SL_PRIV_UTIL_H
 
 #include <libebook/e-book.h>
+#include <libempathy/empathy-contact.h>
 
 /*#define SL_ENABLE_DEBUG_ALL*/
 
@@ -60,6 +61,8 @@
   #define sl_debug_util(format, ...)
 #endif
 
+typedef gchar * (*SlPrivUtilToStringFunc)(gpointer data);
+
 ESource *sl_priv_util_get_source (ESourceList *source_tree, const gchar *name);
 ESourceGroup *sl_priv_util_source_tree_get_default_group
   (ESourceList *source_tree);
@@ -68,7 +71,8 @@
 gboolean sl_priv_util_list_contains (GList *list, gpointer data, GEqualFunc equal);
 void sl_priv_util_hash_table_print (GHashTable *table, const gchar *title);
 void sl_priv_util_hash_table_print_keys (GHashTable *table, const gchar *title);
-void sl_priv_util_list_print (GList *list, const gchar *title);
+gchar *sl_priv_util_imcontact_to_string (EmpathyContact *imcontact);
+void sl_priv_util_list_print (GList *list, const gchar *title, SlPrivUtilToStringFunc to_string);
 void sl_priv_util_eattribute_list_print (GList *eattributes, const gchar *title);
 void sl_priv_util_attribute_list_print (GList *attributes, const gchar *title);
 
@@ -89,4 +93,7 @@
 GList *sl_priv_util_strv_to_list (gchar **strv);
 gchar **sl_priv_util_list_to_strv (GList *strings);
 
+gchar *sl_priv_util_get_account_id_from_imcontact (EmpathyContact *imcontact);
+const gchar *sl_priv_util_get_protocol_name_from_account (McAccount *account);
+
 #endif

Modified: branches/libsoylent-v0.5.0/libsoylent/soylent.c
==============================================================================
--- branches/libsoylent-v0.5.0/libsoylent/soylent.c	(original)
+++ branches/libsoylent-v0.5.0/libsoylent/soylent.c	Mon Aug 18 18:39:42 2008
@@ -21,15 +21,87 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+/**
+ * SECTION:soylent
+ * @short_description: global libsoylent functions
+ * @stability: Unstable
+ * @include: soylent.h
+ *
+ * soylent contains some global functions for libsoylent, like initializing
+ * and cleaning up libsoylent.
+ */
+
 #include "soylent.h"
+#include "sl-priv-util.h"
 
 #include <glib-object.h>
+#include <libempathy/empathy-utils.h>
+#include <libmissioncontrol/mc-account-monitor.h>
+
+/* TODO: the whole communications stuff probably should go into its own
+ * file */
+
+static EmpathyContactManager *contactmgr = NULL;
+static McAccountMonitor *account_monitor = NULL;
+static GHashTable *im_protocols = NULL;
+
+static void
+mc_account_created (McAccountMonitor *account_manager, gchar *name, gpointer user_data)
+{
+  McAccount *account = mc_account_lookup (name);
+  const gchar *protocol_name = sl_priv_util_get_protocol_name_from_account (account);
+  g_hash_table_insert (im_protocols, (gpointer) protocol_name, "");
+  sl_debug_book ("discovered im attribute \"%s\"", protocol_name);
+}
+
+static void
+sl_im_init (void)
+{  
+  MissionControl *mc = empathy_mission_control_new ();
+  
+  im_protocols = g_hash_table_new (g_str_hash, g_str_equal);
+  GList *accounts = mc_accounts_list ();
+  for (; accounts != NULL; accounts = accounts->next)
+    {
+      const gchar *protocol_name = sl_priv_util_get_protocol_name_from_account (accounts->data);
+      g_hash_table_insert (im_protocols, (gpointer) protocol_name, "");
+      sl_debug_book ("discovered im attribute \"%s\"", protocol_name);
+    }
+  accounts = g_list_first (accounts);
+  mc_accounts_list_free (accounts);
+  
+  account_monitor = mc_account_monitor_new ();
+  g_signal_connect (account_monitor, "account-created",
+                    G_CALLBACK (mc_account_created), NULL);
+  
+  
+  /*DBusGConnection *dbus_con = dbus_g_bus_get(DBUS_BUS_SESSION, error);
+	if (dbus_con == NULL) {
+		g_error("fail");
+	}
+	mc = mission_control_new(dbus_con);*/
+  contactmgr = empathy_contact_manager_new ();  
+  mission_control_set_presence(mc, MC_PRESENCE_AVAILABLE, NULL, NULL, NULL);
+}
+
+EmpathyContactManager *
+sl_im_get_contact_manager (void)
+{
+  return contactmgr;
+}
+
+gboolean
+sl_im_is_im_attribute (const gchar *attrname)
+{
+  return (g_hash_table_lookup (im_protocols, attrname) != NULL);
+}
 
 gboolean
 sl_init (GError **error)
 {
 	g_type_init ();
   sl_attributes_init ();
+  sl_im_init ();
 	return sl_book_setup (error);
 }
 

Modified: branches/libsoylent-v0.5.0/libsoylent/soylent.h
==============================================================================
--- branches/libsoylent-v0.5.0/libsoylent/soylent.h	(original)
+++ branches/libsoylent-v0.5.0/libsoylent/soylent.h	Mon Aug 18 18:39:42 2008
@@ -45,6 +45,11 @@
 #include "sl-attributes.h"
 #include "sl-group.h"
 
+#include <libempathy/empathy-contact-manager.h>
+
+EmpathyContactManager *sl_im_get_contact_manager (void);
+gboolean sl_im_is_im_attribute (const gchar *attrname);
+
 gboolean sl_init (GError **error);
 void sl_cleanup (void);
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]