[Galago-commits] r2846 - in branches/libgalago/push-presence: . docs/reference docs/reference/tmpl libgalago tests

galago-commits at freedesktop.org galago-commits at freedesktop.org
Mon Jun 12 23:11:13 PDT 2006


Author: chipx86
Date: 2006-06-12 23:11:06 -0700 (Mon, 12 Jun 2006)
New Revision: 2846

Modified:
   branches/libgalago/push-presence/ChangeLog
   branches/libgalago/push-presence/NEWS
   branches/libgalago/push-presence/docs/reference/libgalago-sections.txt
   branches/libgalago/push-presence/docs/reference/tmpl/galago-service.sgml
   branches/libgalago/push-presence/libgalago/galago-account.c
   branches/libgalago/push-presence/libgalago/galago-account.h
   branches/libgalago/push-presence/libgalago/galago-core.c
   branches/libgalago/push-presence/libgalago/galago-core.h
   branches/libgalago/push-presence/libgalago/galago-dbus.c
   branches/libgalago/push-presence/libgalago/galago-dbus.h
   branches/libgalago/push-presence/libgalago/galago-object.h
   branches/libgalago/push-presence/libgalago/galago-person.c
   branches/libgalago/push-presence/libgalago/galago-presence.c
   branches/libgalago/push-presence/libgalago/galago-private.h
   branches/libgalago/push-presence/libgalago/galago-service.c
   branches/libgalago/push-presence/libgalago/galago-service.h
   branches/libgalago/push-presence/setup-gettext
   branches/libgalago/push-presence/tests/check-libgalago.c
   branches/libgalago/push-presence/tests/test-bug-36.c
Log:
Merge from trunk (r2845).


Modified: branches/libgalago/push-presence/ChangeLog
===================================================================
--- branches/libgalago/push-presence/ChangeLog	2006-06-13 02:59:33 UTC (rev 2845)
+++ branches/libgalago/push-presence/ChangeLog	2006-06-13 06:11:06 UTC (rev 2846)
@@ -1,3 +1,114 @@
+Mon Jun 12 19:59:22 PDT 2006  Christian Hammond <chipx86 at chipx86.com>
+
+	* NEWS:
+	  - Update the NEWS a bit.
+
+Mon Jun 12 19:56:47 PDT 2006  Christian Hammond <chipx86 at chipx86.com>
+
+	* libgalago/galago-account.c:
+	* libgalago/galago-account.h:
+	* libgalago/galago-service.c:
+	  - Added galago_account_get_avatar_async().
+
+Mon Jun 12 19:54:14 PDT 2006  Christian Hammond <chipx86 at chipx86.com>
+
+	* libgalago/galago-presence.c:
+	  - Fix a segfault when an idle start time of 0 is passed to
+	    galago_presence_set_idle_time(). Thanks to kkubasik for finding this.
+	    This closes bug #64.
+
+Mon Jun 12 02:05:46 PDT 2006  Christian Hammond <chipx86 at chipx86.com>
+
+	* libgalago/galago-account.c:
+	* libgalago/galago-account.h:
+	* tests/check-libgalago.c:
+	  - Added galago_account_get_presence_async().
+
+Mon Jun 12 01:51:43 PDT 2006  Christian Hammond <chipx86 at chipx86.com>
+
+	* libgalago/galago-core.c:
+	* libgalago/galago-service.c:
+	  - Documentation fixes.
+
+Mon Jun 12 01:48:44 PDT 2006  Christian Hammond <chipx86 at chipx86.com>
+
+	* libgalago/galago-core.c:
+	* libgalago/galago-core.h:
+	* libgalago/galago-service.h:
+	* tests/check-libgalago.c:
+	  - Implemented galago_get_service_async().
+
+Mon Jun 12 01:34:56 PDT 2006  Christian Hammond <chipx86 at chipx86.com>
+
+	* libgalago/galago-dbus.c:
+	  - Combine a couple loops.
+
+Mon Jun 12 01:33:05 PDT 2006  Christian Hammond <chipx86 at chipx86.com>
+
+	* tests/test-bug-36.c:
+	  - Indicate that the test was successful if it didn't crash after
+	    uninitializing.
+
+Mon Jun 12 01:29:58 PDT 2006  Christian Hammond <chipx86 at chipx86.com>
+
+	* libgalago/galago-dbus.c:
+	* libgalago/galago-private.h:
+	* libgalago/galago-service.c:
+	  - Calls should now return registered call handles, and they should be
+	    cancellable. This is not yet tested.
+
+Mon Jun 12 00:25:24 PDT 2006  Christian Hammond <chipx86 at chipx86.com>
+
+	* docs/reference/tmpl/galago-service.sgml:
+	* libgalago/galago-service.c:
+	* libgalago/galago-service.h:
+	* tests/check-libgalago.c:
+	  - Added a GalagoServiceAccountCb function typedef.
+	  - Extend galago_service_get_account_async() to take a GFreeFunc and
+	    change its GCallback parameter to a GalagoServiceAccountCb.
+
+Sun Jun 11 22:15:48 PDT 2006  Christian Hammond <chipx86 at chipx86.com>
+
+	* libgalago/galago-dbus.c:
+	* libgalago/galago-dbus.h:
+	* libgalago/galago-service.c:
+	* tests/check-libgalago.c:
+	  - Add working asynchronous account retrieval! Most of the code is now
+	    in place to implement the other async functions. It just needs to
+	    return proper call IDs and allow cancelling a request.
+
+Sun Jun 11 20:05:29 PDT 2006  Christian Hammond <chipx86 at chipx86.com>
+
+	* libgalago/galago-account.c:
+	* libgalago/galago-dbus.c:
+	* libgalago/galago-dbus.h:
+	* libgalago/galago-person.c:
+	* libgalago/galago-service.c:
+	  - Push and pop the context inside the D-BUS message sending utility
+	    functions, and remove the calls to push/pop that wrap calls to the
+	    D-BUS functions in the other files. Saves a few lines..
+
+Sun Jun 11 19:36:02 PDT 2006  Christian Hammond <chipx86 at chipx86.com>
+
+	* tests/check-libgalago.c:
+	  - Added some test cases for synchronous and asynchronous calls.
+
+Sun Jun 11 18:16:36 PDT 2006  Christian Hammond <chipx86 at chipx86.com>
+
+	* docs/reference/libgalago-sections.txt:
+	* docs/reference/tmpl/galago-service.sgml:
+	* libgalago/galago-dbus.c:
+	* libgalago/galago-dbus.h:
+	* libgalago/galago-object.h:
+	* libgalago/galago-service.c:
+	* libgalago/galago-service.h:
+	  - Added the beginning of the async functionality:
+	    - Put in a stubbed out galago_service_get_account_async() and
+	      galago_dbus_send_message_with_reply_async().
+	    - Modified galago_dbus_send_message_with_reply_list_vargs() to
+		  handle sending messages and receiving replies both synchronously
+	      and asynchronously.
+
 Fri May 26 00:36:24 PDT 2006  Christian Hammond <chipx86 at chipx86.com>
 
 	A libgalago/galago-status-attr.c:

Modified: branches/libgalago/push-presence/NEWS
===================================================================
--- branches/libgalago/push-presence/NEWS	2006-06-13 02:59:33 UTC (rev 2845)
+++ branches/libgalago/push-presence/NEWS	2006-06-13 06:11:06 UTC (rev 2846)
@@ -1,3 +1,12 @@
+version 0.5.2:
+	* Fixed a crash when passing an idle start time of 0 to
+	  galago_presence_set_idle(). (Bug #64)
+	* Added the following asynchronous query functions:
+	  - galago_account_get_avatar_async
+	  - galago_account_get_presence_async
+	  - galago_get_service_async
+	  - galago_service_get_account_async
+
 version 0.5.1 (May 21, 2006):
 	* Moved to gtk-doc for the documentation. It should now be compatible
 	  with devhelp.

Modified: branches/libgalago/push-presence/docs/reference/libgalago-sections.txt
===================================================================
--- branches/libgalago/push-presence/docs/reference/libgalago-sections.txt	2006-06-13 02:59:33 UTC (rev 2845)
+++ branches/libgalago/push-presence/docs/reference/libgalago-sections.txt	2006-06-13 06:11:06 UTC (rev 2846)
@@ -253,6 +253,7 @@
 galago_service_get_flags
 galago_service_create_account
 galago_service_get_account
+galago_service_get_account_async
 galago_service_get_accounts
 galago_service_normalize
 <SUBSECTION Standard>

Modified: branches/libgalago/push-presence/docs/reference/tmpl/galago-service.sgml
===================================================================
--- branches/libgalago/push-presence/docs/reference/tmpl/galago-service.sgml	2006-06-13 02:59:33 UTC (rev 2845)
+++ branches/libgalago/push-presence/docs/reference/tmpl/galago-service.sgml	2006-06-13 06:11:06 UTC (rev 2846)
@@ -220,6 +220,19 @@
 @Returns: 
 
 
+<!-- ##### FUNCTION galago_service_get_account_async ##### -->
+<para>
+
+</para>
+
+ at service: 
+ at username: 
+ at cb: 
+ at user_data: 
+ at free_func: 
+ at Returns: 
+
+
 <!-- ##### FUNCTION galago_service_get_accounts ##### -->
 <para>
 

Modified: branches/libgalago/push-presence/libgalago/galago-account.c
===================================================================
--- branches/libgalago/push-presence/libgalago/galago-account.c	2006-06-13 02:59:33 UTC (rev 2845)
+++ branches/libgalago/push-presence/libgalago/galago-account.c	2006-06-13 06:11:06 UTC (rev 2846)
@@ -934,15 +934,11 @@
 	if (contact == NULL && query && GALAGO_OBJECT_IS_REMOTE(account) &&
 		!galago_is_daemon() && galago_is_connected())
 	{
-		galago_context_push(galago_object_get_context(GALAGO_OBJECT(account)));
-
 		contact = galago_dbus_send_message_with_reply(GALAGO_OBJECT(account),
 			"GetContact",
 			galago_value_new_object(GALAGO_TYPE_ACCOUNT, NULL),
 			galago_value_new(GALAGO_VALUE_TYPE_STRING, &username, NULL),
 			NULL);
-
-		galago_context_pop();
 	}
 
 	return contact;
@@ -974,16 +970,12 @@
 	{
 		GList *temp;
 
-		galago_context_push(galago_object_get_context(GALAGO_OBJECT(account)));
-
 		temp = galago_dbus_send_message_with_reply(GALAGO_OBJECT(account),
 			"GetContacts",
 			galago_value_new_list(GALAGO_TYPE_OBJECT, NULL,
 								  (void *)GALAGO_TYPE_ACCOUNT),
 			NULL);
 		g_list_free(temp);
-
-		galago_context_pop();
 	}
 
 	return account->priv->contacts;
@@ -1023,25 +1015,98 @@
 GalagoPresence *
 galago_account_get_presence(const GalagoAccount *account, gboolean query)
 {
+	GalagoPresence *presence;
+
 	g_return_val_if_fail(account != NULL,            NULL);
 	g_return_val_if_fail(GALAGO_IS_ACCOUNT(account), NULL);
 
-	if (account->priv->presence == NULL && query &&
+	presence = account->priv->presence;
+
+	if (presence == NULL && query &&
 		GALAGO_OBJECT_IS_REMOTE(account) && !galago_is_daemon() &&
 		galago_is_connected())
 	{
-		account->priv->presence =
+		presence =
 			galago_dbus_send_message_with_reply(GALAGO_OBJECT(account),
 				"GetPresence",
 				galago_value_new_object(GALAGO_TYPE_PRESENCE, NULL),
 				NULL);
-		g_object_notify(G_OBJECT(account), "presence");
 	}
 
-	return account->priv->presence;
+	return presence;
 }
 
 /**
+ * galago_account_get_presence_async
+ * @account:   The account.
+ * @cb:        The callback function that will be passed the presence.
+ * @user_data: Custom data to pass to the callback function.
+ * @free_func: Optional function to free @user_data when the request completes.
+ *
+ * Asynchronously retrieves the presence associated with the specified
+ * account.
+ *
+ * For example:
+ * <informalexample>
+ * <programlisting>
+ *  static void
+ *  presence_received_cb(GalagoAccount *account,
+ *                       GalagoPresence *presence,
+ *                       gpointer user_data)
+ *  {
+ *  }
+ *  
+ *  static void
+ *  get_presence(GalagoAccount *account)
+ *  {
+ *      GalagoCallHandle handle;
+ *  
+ *      handle = galago_account_get_presence_async(account,
+ *                                                 presence_received_cb,
+ *                                                 NULL, NULL);
+ *  }
+ * </programlisting>
+ * </informalexample>
+ *
+ * Returns: A valid #GalagoCallHandle on success. On error, this will return
+ *          %GALAGO_CALL_HANDLE_INVALID.
+ *
+ * Since: 0.5.2
+ */
+GalagoCallHandle
+galago_account_get_presence_async(const GalagoAccount *account,
+								  GalagoAccountPresenceCb cb,
+								  gpointer user_data,
+								  GFreeFunc free_func)
+{
+	GalagoPresence *presence;
+	GalagoCallHandle handle = GALAGO_CALL_HANDLE_INVALID;
+
+	g_return_val_if_fail(account  != NULL,                      handle);
+	g_return_val_if_fail(GALAGO_IS_ACCOUNT(account),            handle);
+	g_return_val_if_fail(cb != NULL,                            handle);
+
+	presence = galago_account_get_presence(account, FALSE);
+
+	if (presence != NULL)
+	{
+		cb((GalagoAccount *)account, presence, user_data);
+		handle = galago_calls_request_dummy_handle();
+	}
+	else if (GALAGO_OBJECT_IS_REMOTE(account) && !galago_is_daemon() &&
+			 galago_is_connected())
+	{
+		handle = galago_dbus_send_message_with_reply_async(
+			GALAGO_OBJECT(account), "GetPresence", G_CALLBACK(cb),
+			user_data, free_func, g_cclosure_marshal_VOID__POINTER,
+			galago_value_new_object(GALAGO_TYPE_PRESENCE, NULL),
+			NULL);
+	}
+
+	return handle;
+}
+
+/**
  * galago_account_set_avatar
  * @account: The account.
  * @avatar:  The avatar to set.
@@ -1087,24 +1152,95 @@
 GalagoImage *
 galago_account_get_avatar(const GalagoAccount *account, gboolean query)
 {
+	GalagoImage *avatar;
+
 	g_return_val_if_fail(account != NULL,            NULL);
 	g_return_val_if_fail(GALAGO_IS_ACCOUNT(account), NULL);
 
-	if (account->priv->avatar == NULL && query &&
-		GALAGO_OBJECT_IS_REMOTE(account) && !galago_is_daemon() &&
-		galago_is_connected())
+	avatar = account->priv->avatar;
+
+	if (avatar == NULL && query && GALAGO_OBJECT_IS_REMOTE(account) &&
+		!galago_is_daemon() && galago_is_connected())
 	{
-		account->priv->avatar =
-			galago_dbus_send_message_with_reply(GALAGO_OBJECT(account),
-				"GetAvatar",
-				galago_value_new_object(GALAGO_TYPE_IMAGE, NULL),
-				NULL);
-		g_object_notify(G_OBJECT(account), "avatar");
+		avatar = galago_dbus_send_message_with_reply(GALAGO_OBJECT(account),
+			"GetAvatar",
+			galago_value_new_object(GALAGO_TYPE_IMAGE, NULL),
+			NULL);
 	}
 
-	return account->priv->avatar;
+	return avatar;
 }
 
+/**
+ * galago_account_get_avatar_async
+ * @account:   The account.
+ * @cb:        The callback function that will be passed the avatar.
+ * @user_data: Custom data to pass to the callback function.
+ * @free_func: Optional function to free @user_data when the request completes.
+ *
+ * Asynchronously retrieves the avatar associated with the specified
+ * account.
+ *
+ * For example:
+ * <informalexample>
+ * <programlisting>
+ *  static void
+ *  avatar_received_cb(GalagoAccount *account,
+ *                     GalagoAvatar *avatar,
+ *                     gpointer user_data)
+ *  {
+ *  }
+ *  
+ *  static void
+ *  get_avatar(GalagoAccount *account)
+ *  {
+ *      GalagoCallHandle handle;
+ *  
+ *      handle = galago_account_get_avatar_async(account,
+ *                                               avatar_received_cb,
+ *                                               NULL, NULL);
+ *  }
+ * </programlisting>
+ * </informalexample>
+ *
+ * Returns: A valid #GalagoCallHandle on success. On error, this will return
+ *          %GALAGO_CALL_HANDLE_INVALID.
+ *
+ * Since: 0.5.2
+ */
+GalagoCallHandle
+galago_account_get_avatar_async(const GalagoAccount *account,
+								GalagoAccountAvatarCb cb,
+								gpointer user_data,
+								GFreeFunc free_func)
+{
+	GalagoImage *avatar;
+	GalagoCallHandle handle = GALAGO_CALL_HANDLE_INVALID;
+
+	g_return_val_if_fail(account  != NULL,                      handle);
+	g_return_val_if_fail(GALAGO_IS_ACCOUNT(account),            handle);
+	g_return_val_if_fail(cb != NULL,                            handle);
+
+	avatar = galago_account_get_avatar(account, FALSE);
+
+	if (avatar != NULL)
+	{
+		cb((GalagoAccount *)account, avatar, user_data);
+		handle = galago_calls_request_dummy_handle();
+	}
+	else if (GALAGO_OBJECT_IS_REMOTE(account) && !galago_is_daemon() &&
+			 galago_is_connected())
+	{
+		handle = galago_dbus_send_message_with_reply_async(
+			GALAGO_OBJECT(account), "GetAvatar", G_CALLBACK(cb),
+			user_data, free_func, g_cclosure_marshal_VOID__POINTER,
+			galago_value_new_object(GALAGO_TYPE_IMAGE, NULL),
+			NULL);
+	}
+
+	return handle;
+}
+
 void
 _galago_account_set_presence(GalagoAccount *account, GalagoPresence *presence)
 {

Modified: branches/libgalago/push-presence/libgalago/galago-account.h
===================================================================
--- branches/libgalago/push-presence/libgalago/galago-account.h	2006-06-13 02:59:33 UTC (rev 2845)
+++ branches/libgalago/push-presence/libgalago/galago-account.h	2006-06-13 06:11:06 UTC (rev 2846)
@@ -31,6 +31,11 @@
 #include <libgalago/galago-presence.h>
 #include <libgalago/galago-service.h>
 
+typedef void (*GalagoAccountPresenceCb)(GalagoAccount *, GalagoPresence *,
+										gpointer);
+typedef void (*GalagoAccountAvatarCb)(GalagoAccount *, GalagoImage *,
+									  gpointer);
+
 struct _GalagoAccount
 {
 	GalagoObject parent_object;
@@ -113,10 +118,20 @@
 GalagoPresence *galago_account_create_presence(GalagoAccount *account);
 GalagoPresence *galago_account_get_presence(const GalagoAccount *account,
 											gboolean query);
+GalagoCallHandle galago_account_get_presence_async(
+	const GalagoAccount *account,
+	GalagoAccountPresenceCb cb,
+	gpointer user_data,
+	GFreeFunc free_func);
 
 void galago_account_set_avatar(GalagoAccount *account, GalagoImage *avatar);
 GalagoImage *galago_account_get_avatar(const GalagoAccount *account,
 									   gboolean query);
+GalagoCallHandle galago_account_get_avatar_async(
+	const GalagoAccount *account,
+	GalagoAccountAvatarCb cb,
+	gpointer user_data,
+	GFreeFunc free_func);
 
 G_END_DECLS
 

Modified: branches/libgalago/push-presence/libgalago/galago-core.c
===================================================================
--- branches/libgalago/push-presence/libgalago/galago-core.c	2006-06-13 02:59:33 UTC (rev 2845)
+++ branches/libgalago/push-presence/libgalago/galago-core.c	2006-06-13 06:11:06 UTC (rev 2846)
@@ -1244,6 +1244,78 @@
 }
 
 /**
+ * galago_get_service_async:
+ * @id:        The service ID.
+ * @cb:        The callback function that will be passed the service.
+ * @user_data: Custom data to pass to the callback function.
+ * @free_func: Optional function to free @user_data when the request completes.
+ *
+ * Asynchronously retrieves the service with the specified ID.
+ *
+ * For example:
+ * <informalexample>
+ * <programlisting>
+ *  static void
+ *  service_received_cb(GalagoCore *core,
+ *                      GalagoService *service,
+ *                      gpointer user_data)
+ *  {
+ *  }
+ *  
+ *  static void
+ *  get_jabber_service(void)
+ *  {
+ *      GalagoCallHandle handle;
+ *  
+ *      handle = galago_get_service_async("jabber", service_received_cb,
+ *                                        NULL, NULL);
+ *  }
+ * </programlisting>
+ * </informalexample>
+ *
+ * Returns: A valid #GalagoCallHandle on success. On error, this will return
+ *          %GALAGO_CALL_HANDLE_INVALID.
+ *
+ * Since: 0.5.2
+ */
+GalagoCallHandle
+galago_get_service_async(const char *id,
+						 GalagoCoreServiceCb cb,
+						 gpointer user_data,
+						 GFreeFunc free_func)
+{
+	GalagoService *service;
+	GalagoCallHandle handle = GALAGO_CALL_HANDLE_INVALID;
+
+	g_return_val_if_fail(galago_is_initted(),       handle);
+	g_return_val_if_fail(id != NULL && *id != '\0', handle);
+	g_return_val_if_fail(cb != NULL,                handle);
+
+	galago_context_push(galago_object_get_context(GALAGO_OBJECT(_core)));
+
+	service = galago_context_get_service(id, GALAGO_REMOTE);
+
+	if (service != NULL)
+	{
+		cb(_core, service, user_data);
+		handle = galago_calls_request_dummy_handle();
+	}
+	else if (!galago_is_daemon() && galago_is_connected())
+	{
+		handle = galago_dbus_send_message_with_reply_async(
+			GALAGO_OBJECT(_core), "GetService", G_CALLBACK(cb),
+			user_data, free_func, g_cclosure_marshal_VOID__POINTER,
+			galago_value_new_object(GALAGO_TYPE_SERVICE, NULL),
+			galago_value_new(GALAGO_VALUE_TYPE_STRING, &id, NULL),
+			NULL);
+	}
+
+	galago_context_pop();
+
+	return handle;
+}
+
+/**
  * galago_get_services
  * @origin: The desired origin.
  * @query:  TRUE if a remote query should be done if there are no

Modified: branches/libgalago/push-presence/libgalago/galago-core.h
===================================================================
--- branches/libgalago/push-presence/libgalago/galago-core.h	2006-06-13 02:59:33 UTC (rev 2845)
+++ branches/libgalago/push-presence/libgalago/galago-core.h	2006-06-13 06:11:06 UTC (rev 2846)
@@ -50,6 +50,8 @@
 typedef struct _GalagoCoreClass   GalagoCoreClass;
 typedef struct _GalagoCorePrivate GalagoCorePrivate;
 
+typedef void (*GalagoCoreServiceCb)(GalagoCore *, GalagoService *, gpointer);
+
 typedef enum
 {
 	GALAGO_INIT_CLIENT      = 0,
@@ -58,7 +60,6 @@
 
 } GalagoInitFlags;
 
-
 struct _GalagoCore
 {
 	GalagoObject parent_object;
@@ -110,6 +111,10 @@
 									 GalagoServiceFlags flags);
 GalagoService *galago_get_service(const char *id, GalagoOrigin origin,
 								  gboolean query);
+GalagoCallHandle galago_get_service_async(const char *id,
+										  GalagoCoreServiceCb cb,
+										  gpointer user_data,
+										  GFreeFunc free_func);
 GList *galago_get_services(GalagoOrigin origin, gboolean query);
 
 GalagoPerson *galago_create_person(const char *uid);

Modified: branches/libgalago/push-presence/libgalago/galago-dbus.c
===================================================================
--- branches/libgalago/push-presence/libgalago/galago-dbus.c	2006-06-13 02:59:33 UTC (rev 2845)
+++ branches/libgalago/push-presence/libgalago/galago-dbus.c	2006-06-13 06:11:06 UTC (rev 2846)
@@ -20,11 +20,98 @@
  */
 #include <libgalago/galago-dbus.h>
 #include <libgalago/galago-assert.h>
+#include <libgalago/galago-context.h>
 #include <libgalago/galago-core.h>
 #include <string.h>
 #include <stdio.h>
 
+typedef void (*PendingCallCb)(const GalagoObject *, GList *, gpointer);
+
+typedef struct
+{
+	const GalagoObject *object;
+	char *name;
+	GList *return_types;
+	PendingCallCb cb;
+	gpointer user_data;
+	GalagoCallHandle handle;
+
+} PendingCallData;
+
+G_LOCK_DEFINE_STATIC(_calls_lock);
+static guint _next_call_handle = 1;
+static GHashTable *_active_calls = NULL;
+
+static void
+pending_call_data_free(PendingCallData *data)
+{
+	if (data->return_types != NULL)
+	{
+		g_list_foreach(data->return_types, (GFunc)galago_value_destroy, NULL);
+		g_list_free(data->return_types);
+	}
+
+	g_free(data->name);
+	g_free(data);
+}
+
 /**
+ * galago_call_cancel:
+ * @handle: The call handle to cancel.
+ *
+ * Cancels an asynchronous call.
+ */
+void
+galago_call_cancel(GalagoCallHandle handle)
+{
+	DBusPendingCall *call;
+
+	G_LOCK(_calls_lock);
+
+	call = g_hash_table_lookup(_active_calls, GINT_TO_POINTER(handle));
+
+	if (call != NULL)
+	{
+		g_hash_table_remove(_active_calls, GINT_TO_POINTER(handle));
+		dbus_pending_call_cancel(call);
+	}
+
+	G_UNLOCK(_calls_lock);
+}
+
+GalagoCallHandle
+galago_calls_request_dummy_handle(void)
+{
+	GalagoCallHandle handle;
+
+	G_LOCK(_calls_lock);
+	handle = _next_call_handle++;
+	G_UNLOCK(_calls_lock);
+
+	return handle;
+}
+
+static GalagoCallHandle
+galago_calls_request_handle(DBusPendingCall *call)
+{
+	GalagoCallHandle handle;
+
+	g_return_val_if_fail(call != NULL, GALAGO_CALL_HANDLE_INVALID);
+
+	G_LOCK(_calls_lock);
+
+	if (_active_calls == NULL)
+		_active_calls = g_hash_table_new(g_direct_hash, g_direct_equal);
+
+	handle = _next_call_handle++;
+	g_hash_table_insert(_active_calls, GINT_TO_POINTER(handle), call);
+
+	G_UNLOCK(_calls_lock);
+
+	return handle;
+}
+
+/**
  * galago_dbus_message_iter_append_string_or_nil
  * @iter: The message iterator.
  * @str:  The string, or NULL.
@@ -142,7 +229,6 @@
  * @iter: The D-BUS message iterator.
  * @type: The GType.
  *
- *
  * Returns an object of the specified type from a D-BUS message.
  *
  * Returns: The object.
@@ -649,16 +735,98 @@
 }
 
 static GList *
+message_reply_received_cb(DBusMessage *message, GList *return_types)
+{
+	GList *ret_list = NULL, *l;
+	DBusMessageIter iter;
+
+	dbus_message_iter_init(message, &iter);
+
+	for (l = return_types; l != NULL; l = l->next)
+	{
+		GalagoValue *value = (GalagoValue *)l->data;
+		ret_list = g_list_append(ret_list,
+								 get_ret_val_from_iter(&iter, value));
+		galago_value_destroy(value);
+
+		dbus_message_iter_next(&iter);
+	}
+
+	g_list_free(return_types);
+
+	return ret_list;
+}
+
+static void
+handle_pending_call_error(const GalagoObject *object, const char *name,
+						  DBusError *error)
+{
+	if (!dbus_error_has_name(error, GALAGO_DBUS_ERROR_OBJECT_NOT_FOUND))
+	{
+		g_warning("Error sending %s.%s: %s",
+				  g_type_name(G_OBJECT_TYPE(object)), name, error->message);
+	}
+}
+
+static void
+pending_call_done_cb(DBusPendingCall *call, gpointer user_data)
+{
+	PendingCallData *call_data = (PendingCallData *)user_data;
+	DBusMessage *reply = NULL;
+	GList *ret_list;
+
+	if (!dbus_pending_call_get_completed(call))
+		goto exit;
+
+	reply = dbus_pending_call_steal_reply(call);
+
+	if (reply == NULL)
+		goto exit;
+
+	if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR)
+	{
+		DBusError error;
+
+		dbus_error_init(&error);
+		dbus_set_error_from_message(&error, reply);
+		handle_pending_call_error(call_data->object, call_data->name, &error);
+		dbus_error_free(&error);
+
+		goto exit;
+	}
+
+	galago_context_push(galago_object_get_context(call_data->object));
+	ret_list = message_reply_received_cb(reply, call_data->return_types);
+	galago_context_pop();
+
+	call_data->cb(call_data->object, ret_list, call_data->user_data);
+
+	/* Hack to prevent this from being freed later. */
+	call_data->return_types = NULL;
+
+exit:
+	if (reply != NULL)
+		dbus_message_unref(reply);
+
+	G_LOCK(_calls_lock);
+	g_hash_table_remove(_active_calls, GINT_TO_POINTER(call_data->handle));
+	G_UNLOCK(_calls_lock);
+
+	dbus_pending_call_unref(call);
+}
+
+static GList *
 galago_dbus_send_message_with_reply_list_vargs(const GalagoObject *object,
 											   const char *name,
 											   GList *return_types,
-											   va_list args)
+											   va_list args,
+											   PendingCallCb cb,
+											   gpointer user_data,
+											   GalagoCallHandle *handle)
 {
-	DBusMessage *message;
-	DBusMessage *reply = NULL;
-	DBusMessageIter iter;
+	DBusMessage *message = NULL;
 	DBusError error;
-	GList *ret_list = NULL, *l;
+	GList *ret_list = NULL;
 
 	galago_goto_if_fail(object != NULL,           exit);
 	galago_goto_if_fail(name   != NULL,           exit);
@@ -676,45 +844,54 @@
 
 	galago_goto_if_fail(message != NULL, exit);
 
-	reply = dbus_connection_send_with_reply_and_block(
-		galago_get_dbus_conn(), message, -1, &error);
+	if (cb == NULL)
+	{
+		/* Synchronous */
+		DBusMessage *reply;
 
-	dbus_message_unref(message);
+		reply = dbus_connection_send_with_reply_and_block(
+			galago_get_dbus_conn(), message, -1, &error);
 
-	if (dbus_error_is_set(&error))
-	{
-		if (!dbus_error_has_name(&error, GALAGO_DBUS_ERROR_OBJECT_NOT_FOUND))
+		if (dbus_error_is_set(&error))
 		{
-			g_warning("Error sending %s.%s: %s",
-					  g_type_name(G_OBJECT_TYPE(object)),
-					  name, error.message);
+			handle_pending_call_error(object, name, &error);
+			goto exit;
 		}
 
-		goto exit;
+		galago_context_push(galago_object_get_context(object));
+		ret_list = message_reply_received_cb(reply, return_types);
+		galago_context_pop();
 	}
+	else
+	{
+		/* Asynchronous */
+		DBusPendingCall *call = NULL;
+		PendingCallData *call_data;
 
-	dbus_message_iter_init(reply, &iter);
+		dbus_connection_send_with_reply(galago_get_dbus_conn(),
+										message, &call, -1);
 
-	for (l = return_types; l != NULL; l = l->next)
-	{
-		ret_list = g_list_append(ret_list,
-			get_ret_val_from_iter(&iter, (GalagoValue *)l->data));
+		call_data = g_new0(PendingCallData, 1);
+		call_data->object = object;
+		call_data->name = g_strdup(name);
+		call_data->return_types = return_types;
+		call_data->cb = cb;
+		call_data->user_data = user_data;
+		call_data->handle = galago_calls_request_handle(call);
 
-		dbus_message_iter_next(&iter);
+		if (handle != NULL)
+			*handle = call_data->handle;
+
+		dbus_pending_call_set_notify(call, pending_call_done_cb, call_data,
+									 (DBusFreeFunction)pending_call_data_free);
 	}
 
 exit:
+	if (message != NULL)
+		dbus_message_unref(message);
+
 	dbus_error_free(&error);
 
-	if (reply != NULL)
-		dbus_message_unref(reply);
-
-	if (return_types != NULL)
-	{
-		g_list_foreach(return_types, (GFunc)galago_value_destroy, NULL);
-		g_list_free(return_types);
-	}
-
 	return ret_list;
 }
 
@@ -743,7 +920,8 @@
 
 	va_start(args, return_types);
 	list = galago_dbus_send_message_with_reply_list_vargs(object, name,
-														  return_types, args);
+														  return_types, args,
+														  NULL, NULL, NULL);
 	va_end(args);
 
 	return list;
@@ -774,7 +952,8 @@
 
 	va_start(args, return_type);
 	list = galago_dbus_send_message_with_reply_list_vargs(
-		object, name, g_list_append(NULL, return_type), args);
+		object, name, g_list_append(NULL, return_type), args,
+		NULL, NULL, NULL);
 	va_end(args);
 
 	if (list != NULL)
@@ -787,6 +966,60 @@
 	return retval;
 }
 
+static void
+galago_dbus_send_message_with_reply_async_cb(const GalagoObject *object,
+											 GList *list,
+											 gpointer user_data)
+{
+	GClosure *closure = (GClosure *)user_data;
+	GValue params[2] = {{0, }, {0, }};
+
+	/* For now.. */
+	g_assert(g_list_length(list) == 1);
+	g_assert(list != NULL);
+	g_assert(GALAGO_IS_OBJECT(list->data));
+
+	g_value_init(&params[0], G_TYPE_FROM_INSTANCE(object));
+	g_value_set_instance(&params[0], (gpointer)object);
+
+	g_value_init(&params[1], G_TYPE_FROM_INSTANCE(list->data));
+	g_value_set_instance(&params[1], list->data);
+
+	g_closure_invoke(closure, NULL, 2, params, NULL);
+	g_closure_unref(closure);
+
+	g_value_unset(&params[0]);
+	g_value_unset(&params[1]);
+}
+
+GalagoCallHandle
+galago_dbus_send_message_with_reply_async(const GalagoObject *object,
+										  const char *name,
+										  GCallback cb, gpointer user_data,
+										  GFreeFunc destroy_data,
+										  GClosureMarshal marshal,
+										  GalagoValue *return_type, ...)
+{
+	va_list args;
+	GalagoCallHandle handle;
+	GClosure *closure;
+
+	closure = g_cclosure_new(cb, user_data, (GClosureNotify)destroy_data);
+	g_closure_ref(closure);
+	g_closure_sink(closure);
+	g_closure_set_marshal(closure, marshal);
+	g_object_watch_closure(G_OBJECT(object), closure);
+
+	va_start(args, return_type);
+	galago_dbus_send_message_with_reply_list_vargs(
+		object, name, g_list_append(NULL, return_type), args,
+		galago_dbus_send_message_with_reply_async_cb, closure, &handle);
+	va_end(args);
+
+	return handle;
+}
+
+
 /**
  * galago_dbus_object_push_full
  * @object: The object to push.

Modified: branches/libgalago/push-presence/libgalago/galago-dbus.h
===================================================================
--- branches/libgalago/push-presence/libgalago/galago-dbus.h	2006-06-13 02:59:33 UTC (rev 2845)
+++ branches/libgalago/push-presence/libgalago/galago-dbus.h	2006-06-13 06:11:06 UTC (rev 2846)
@@ -67,6 +67,14 @@
 void *galago_dbus_send_message_with_reply(const GalagoObject *object,
 										  const char *name,
 										  GalagoValue *return_type, ...);
+GalagoCallHandle galago_dbus_send_message_with_reply_async(
+	const GalagoObject *object,
+	const char *name,
+	GCallback cb,
+	gpointer user_data,
+	GFreeFunc destroy_data,
+	GClosureMarshal marshal,
+	GalagoValue *return_value, ...);
 
 void galago_dbus_object_push_full(GalagoObject *object);
 

Modified: branches/libgalago/push-presence/libgalago/galago-object.h
===================================================================
--- branches/libgalago/push-presence/libgalago/galago-object.h	2006-06-13 02:59:33 UTC (rev 2845)
+++ branches/libgalago/push-presence/libgalago/galago-object.h	2006-06-13 06:11:06 UTC (rev 2846)
@@ -122,6 +122,9 @@
 #define GALAGO_OBJECT_IS_REMOTE(obj) \
 	(galago_object_get_origin(GALAGO_OBJECT(obj)) == GALAGO_REMOTE)
 
+typedef guint GalagoCallHandle;
+#define GALAGO_CALL_HANDLE_INVALID ((GalagoCallHandle)0)
+
 #include <libgalago/galago-context-base.h>
 
 G_BEGIN_DECLS

Modified: branches/libgalago/push-presence/libgalago/galago-person.c
===================================================================
--- branches/libgalago/push-presence/libgalago/galago-person.c	2006-06-13 02:59:33 UTC (rev 2845)
+++ branches/libgalago/push-presence/libgalago/galago-person.c	2006-06-13 06:11:06 UTC (rev 2846)
@@ -706,13 +706,11 @@
 	if (query && GALAGO_OBJECT_IS_REMOTE(person) && !galago_is_daemon() &&
 		galago_is_connected())
 	{
-		galago_context_push(galago_object_get_context(GALAGO_OBJECT(person)));
 		g_list_free(galago_dbus_send_message_with_reply(GALAGO_OBJECT(person),
 			"GetAccounts",
 			galago_value_new_list(GALAGO_VALUE_TYPE_OBJECT, NULL,
 								  (void *)GALAGO_TYPE_ACCOUNT),
 			NULL));
-		galago_context_pop();
 	}
 
 	return person->priv->accounts;
@@ -873,16 +871,12 @@
 	if (account == NULL && query && GALAGO_OBJECT_IS_REMOTE(person) &&
 		!galago_is_daemon() && galago_is_connected())
 	{
-		galago_context_push(galago_object_get_context(GALAGO_OBJECT(person)));
-
 		account = galago_dbus_send_message_with_reply(
 			GALAGO_OBJECT(person), "GetAccount",
 			galago_value_new_object(GALAGO_TYPE_ACCOUNT, NULL),
 			galago_value_new_object(GALAGO_TYPE_SERVICE, G_OBJECT(service)),
 			galago_value_new(GALAGO_VALUE_TYPE_STRING, &username, NULL),
 			NULL);
-
-		galago_context_pop();
 	}
 
 	return account;

Modified: branches/libgalago/push-presence/libgalago/galago-presence.c
===================================================================
--- branches/libgalago/push-presence/libgalago/galago-presence.c	2006-06-13 02:59:33 UTC (rev 2845)
+++ branches/libgalago/push-presence/libgalago/galago-presence.c	2006-06-13 06:11:06 UTC (rev 2846)
@@ -406,7 +406,7 @@
 
 	g_return_if_fail(presence != NULL);
 	g_return_if_fail(GALAGO_IS_PRESENCE(presence));
-	g_assert(!idle || idle_start_time > 0);
+	g_return_if_fail(!idle || idle_start_time >= 0);
 
 	if (presence->priv->idle == idle &&
 		presence->priv->idle_start_time == idle_start_time)

Modified: branches/libgalago/push-presence/libgalago/galago-private.h
===================================================================
--- branches/libgalago/push-presence/libgalago/galago-private.h	2006-06-13 02:59:33 UTC (rev 2845)
+++ branches/libgalago/push-presence/libgalago/galago-private.h	2006-06-13 06:11:06 UTC (rev 2846)
@@ -122,4 +122,6 @@
 GalagoPresence *_galago_presence_new(GalagoAccount *account,
 									 const char *obj_path);
 
+GalagoCallHandle galago_calls_request_dummy_handle(void);
+
 #endif /* _GALAGO_PRIVATE_H_ */

Modified: branches/libgalago/push-presence/libgalago/galago-service.c
===================================================================
--- branches/libgalago/push-presence/libgalago/galago-service.c	2006-06-13 02:59:33 UTC (rev 2845)
+++ branches/libgalago/push-presence/libgalago/galago-service.c	2006-06-13 06:11:06 UTC (rev 2846)
@@ -141,21 +141,24 @@
 						   "The service flags",
 						   GALAGO_TYPE_SERVICE_FLAGS, 0,
 						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
-						   G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
+						   G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK |
+						   G_PARAM_STATIC_BLURB));
 
 	g_object_class_install_property(gobject_class, PROP_ID,
 		g_param_spec_string("id", "ID",
 						   "The service's unique ID",
 						   NULL,
 						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
-						   G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
+						   G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK |
+						   G_PARAM_STATIC_BLURB));
 
 	g_object_class_install_property(gobject_class, PROP_NAME,
 		g_param_spec_string("name", "Name",
 						   "The service's name",
 						   NULL,
 						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
-						   G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
+						   G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK |
+						   G_PARAM_STATIC_BLURB));
 }
 
 static void
@@ -634,6 +637,7 @@
 
 	g_return_val_if_fail(service  != NULL,           NULL);
 	g_return_val_if_fail(username != NULL,           NULL);
+	g_return_val_if_fail(*username != '\0',          NULL);
 	g_return_val_if_fail(GALAGO_IS_SERVICE(service), NULL);
 
 	norm_username = galago_service_normalize(service, username);
@@ -644,21 +648,91 @@
 	if (account == NULL && query && GALAGO_OBJECT_IS_REMOTE(service) &&
 		!galago_is_daemon() && galago_is_connected())
 	{
-		galago_context_push(galago_object_get_context(GALAGO_OBJECT(service)));
-
 		account = galago_dbus_send_message_with_reply(
 			GALAGO_OBJECT(service), "GetAccount",
 			galago_value_new_object(GALAGO_TYPE_ACCOUNT, NULL),
 			galago_value_new(GALAGO_VALUE_TYPE_STRING, &username, NULL),
 			NULL);
-
-		galago_context_pop();
 	}
 
 	return account;
 }
 
 /**
+ * galago_service_get_account_async
+ * @service:   The service.
+ * @username:  The account's username.
+ * @cb:        The callback function that will be passed the account.
+ * @user_data: Custom data to pass to the callback function.
+ * @free_func: Optional function to free @user_data when the request completes.
+ *
+ * Asynchronously retrieves the account with the specified username from
+ * a service.
+ *
+ * For example:
+ * <informalexample>
+ * <programlisting>
+ *  static void
+ *  account_received_cb(GalagoService *service,
+ *                      GalagoAccount *account,
+ *                      gpointer user_data)
+ *  {
+ *  }
+ *  
+ *  static void
+ *  get_bob_account(GalagoService *service)
+ *  {
+ *      GalagoCallHandle handle;
+ *  
+ *      handle = galago_service_get_account_async(service, "Bob",
+ *                                                account_received_cb,
+ *                                                NULL, NULL);
+ *  }
+ * </programlisting>
+ * </informalexample>
+ *
+ * Returns: A valid #GalagoCallHandle on success. On error, this will return
+ *          %GALAGO_CALL_HANDLE_INVALID.
+ *
+ * Since: 0.5.2
+ */
+GalagoCallHandle
+galago_service_get_account_async(const GalagoService *service,
+								 const char *username,
+								 GalagoServiceAccountCb cb,
+								 gpointer user_data,
+								 GFreeFunc free_func)
+{
+	GalagoAccount *account;
+	GalagoCallHandle handle = GALAGO_CALL_HANDLE_INVALID;
+
+	g_return_val_if_fail(service  != NULL,                      handle);
+	g_return_val_if_fail(GALAGO_IS_SERVICE(service),            handle);
+	g_return_val_if_fail(username != NULL && *username != '\0', handle);
+	g_return_val_if_fail(cb != NULL,                            handle);
+
+	account = galago_service_get_account(service, username, FALSE);
+
+	if (account != NULL)
+	{
+		cb((GalagoService *)service, account, user_data);
+		handle = galago_calls_request_dummy_handle();
+	}
+	else if (GALAGO_OBJECT_IS_REMOTE(service) && !galago_is_daemon() &&
+			 galago_is_connected())
+	{
+		handle = galago_dbus_send_message_with_reply_async(
+			GALAGO_OBJECT(service), "GetAccount", G_CALLBACK(cb),
+			user_data, free_func, g_cclosure_marshal_VOID__POINTER,
+			galago_value_new_object(GALAGO_TYPE_ACCOUNT, NULL),
+			galago_value_new(GALAGO_VALUE_TYPE_STRING, &username, NULL),
+			NULL);
+	}
+
+	return handle;
+}
+
+/**
  * galago_service_get_accounts
  * @service: The service.
  * @query:   TRUE if a remote query should be done if there is no
@@ -684,16 +758,12 @@
 	{
 		GList *temp;
 
-		galago_context_push(galago_object_get_context(GALAGO_OBJECT(service)));
-
 		temp = galago_dbus_send_message_with_reply(
 			GALAGO_OBJECT(service), "GetAccounts",
 			galago_value_new_list(GALAGO_VALUE_TYPE_OBJECT, NULL,
 								  (void *)GALAGO_TYPE_ACCOUNT),
 			NULL);
 		g_list_free(temp);
-
-		galago_context_pop();
 	}
 
 	return service->priv->accounts;

Modified: branches/libgalago/push-presence/libgalago/galago-service.h
===================================================================
--- branches/libgalago/push-presence/libgalago/galago-service.h	2006-06-13 02:59:33 UTC (rev 2845)
+++ branches/libgalago/push-presence/libgalago/galago-service.h	2006-06-13 06:11:06 UTC (rev 2846)
@@ -35,12 +35,16 @@
 
 	/* Strip a slash and everything after it during normalization. */
 	GALAGO_STRIP_SLASH     = 1 << 2
+
 } GalagoServiceFlags;
 
 #include <libgalago/galago-account.h>
 #include <libgalago/galago-object.h>
 #include <libgalago/galago-status-type.h>
 
+typedef void (*GalagoServiceAccountCb)(GalagoService *, GalagoAccount *,
+									   gpointer);
+
 struct _GalagoService
 {
 	GalagoObject parent_object;
@@ -127,6 +131,12 @@
 GalagoAccount *galago_service_get_account(const GalagoService *service,
 										  const char *username,
 										  gboolean query);
+GalagoCallHandle galago_service_get_account_async(
+	const GalagoService *service,
+	const char *username,
+	GalagoServiceAccountCb cb,
+	gpointer user_data,
+	GFreeFunc free_func);
 GList *galago_service_get_accounts(const GalagoService *service,
 								   gboolean query);
 

Modified: branches/libgalago/push-presence/setup-gettext
===================================================================
--- branches/libgalago/push-presence/setup-gettext	2006-06-13 02:59:33 UTC (rev 2845)
+++ branches/libgalago/push-presence/setup-gettext	2006-06-13 06:11:06 UTC (rev 2846)
@@ -179,7 +179,7 @@
 	echo n | autopoint --force || abort
 	restore_m4
 
-	if test $GETTEXT_MINOR_VERSION -ge 12 -a $GETTEXT_MINOR_VERSION -lt 14; then
+	if test $GETTEXT_MINOR_VERSION -ge 12 -a $GETTEXT_MINOR_VERSION -le 14; then
 		cp po/Makefile.in.in po/.tmp-Makefile.in.in
 		sed -e 's#echo "\$(top_builddir)/\$(MKINSTALLDIRS)" ;; esac#echo "\$(MKINSTALLDIRS)" ;; esac#1' < po/.tmp-Makefile.in.in > po/Makefile.in.in
 		rm po/.tmp-Makefile.in.in

Modified: branches/libgalago/push-presence/tests/check-libgalago.c
===================================================================
--- branches/libgalago/push-presence/tests/check-libgalago.c	2006-06-13 02:59:33 UTC (rev 2845)
+++ branches/libgalago/push-presence/tests/check-libgalago.c	2006-06-13 06:11:06 UTC (rev 2846)
@@ -354,6 +354,134 @@
 
 
 /**************************************************************************
+ * Test synchronous calls
+ **************************************************************************/
+START_TEST(test_service_get_account)
+{
+	GalagoService *service;
+	GalagoAccount *account;
+
+	galago_init("check-libgalago", GALAGO_INIT_CLIENT);
+
+	service = galago_get_service("aim", GALAGO_REMOTE, TRUE);
+	fail_unless(service != NULL,
+				"Couldn't fetch aim service. Is presence-feed running?");
+
+	account = galago_service_get_account(service, "GalagoAIMUser", TRUE);
+	fail_unless(service != NULL,
+				"Couldn't get account GalagoAIMUser. "
+				"Is presence-feed running?");
+}
+END_TEST
+
+
+/**************************************************************************
+ * Test asynchronous calls
+ **************************************************************************/
+static void
+service_received_cb(GalagoCore *core, GalagoService *service,
+					gpointer user_data)
+{
+	GMainLoop *loop = (GMainLoop *)user_data;
+
+	fail_unless(service != NULL && GALAGO_IS_SERVICE(service) &&
+				!strcmp(galago_service_get_id(service), "aim"),
+				"Retrieved incorrect service parameter.");
+
+	g_main_loop_quit(loop);
+}
+
+START_TEST(test_core_get_service_async)
+{
+	GMainLoop *loop;
+
+	loop = g_main_loop_new(NULL, FALSE);
+	galago_init("check-libgalago", GALAGO_INIT_CLIENT);
+	galago_get_service_async("aim", service_received_cb, loop, NULL);
+	g_main_loop_run(loop);
+}
+END_TEST
+
+
+static void
+account_received_cb(GalagoService *service, GalagoAccount *account,
+					gpointer user_data)
+{
+	GMainLoop *loop = (GMainLoop *)user_data;
+
+	fail_unless(service != NULL && GALAGO_IS_SERVICE(service) &&
+				!strcmp(galago_service_get_id(service), "aim"),
+				"Retrieved incorrect service parameter.");
+
+	fail_unless(account != NULL && GALAGO_IS_ACCOUNT(account) &&
+				!strcmp(galago_account_get_username(account), "GalagoAIMUser"),
+				"Retrieved incorrect account parameter.");
+
+	g_main_loop_quit(loop);
+}
+
+START_TEST(test_service_get_account_async)
+{
+	GalagoService *service;
+	GMainLoop *loop;
+
+	loop = g_main_loop_new(NULL, FALSE);
+
+	galago_init("check-libgalago", GALAGO_INIT_CLIENT);
+
+	service = galago_get_service("aim", GALAGO_REMOTE, TRUE);
+	fail_unless(service != NULL,
+				"Couldn't fetch aim service. Is presence-feed running?");
+
+	galago_service_get_account_async(service, "GalagoAIMUser",
+									 account_received_cb, loop, NULL);
+
+	g_main_loop_run(loop);
+}
+END_TEST
+
+static void
+presence_received_cb(GalagoAccount *account, GalagoPresence *presence,
+					 gpointer user_data)
+{
+	GMainLoop *loop = (GMainLoop *)user_data;
+
+	fail_unless(account != NULL && GALAGO_IS_ACCOUNT(account) &&
+				!strcmp(galago_account_get_username(account), "GalagoAIMUser"),
+				"Retrieved incorrect account parameter.");
+
+	fail_unless(presence != NULL && GALAGO_IS_PRESENCE(presence),
+				"Retrieved incorrect presence parameter.");
+
+	g_main_loop_quit(loop);
+}
+
+START_TEST(test_account_get_presence_async)
+{
+	GalagoService *service;
+	GalagoAccount *account;
+	GMainLoop *loop;
+
+	loop = g_main_loop_new(NULL, FALSE);
+
+	galago_init("check-libgalago", GALAGO_INIT_CLIENT);
+
+	service = galago_get_service("aim", GALAGO_REMOTE, TRUE);
+	fail_unless(service != NULL,
+				"Couldn't fetch aim service. Is presence-feed running?");
+
+	account = galago_service_get_account(service, "GalagoAIMUser", TRUE);
+	fail_unless(service != NULL,
+				"Couldn't fetch GalagoAIMUser. Is presence-feed running?");
+
+	galago_account_get_presence_async(account, presence_received_cb, loop,
+									  NULL);
+
+	g_main_loop_run(loop);
+}
+END_TEST
+
+/**************************************************************************
  * Core tests
  **************************************************************************/
 START_TEST(test_core)
@@ -402,6 +530,14 @@
 	/* Test the Service object */
 	ADD_TCASE("service_normalize", test_service_normalize);
 
+	/* Test synchronous queries */
+	ADD_TCASE("service_get_account", test_service_get_account);
+
+	/* Test asynchronous queries */
+	ADD_TCASE("core_get_service_async", test_core_get_service_async);
+	ADD_TCASE("service_get_account_async", test_service_get_account_async);
+	ADD_TCASE("account_get_presence_async", test_account_get_presence_async);
+
 	return s;
 }
 

Modified: branches/libgalago/push-presence/tests/test-bug-36.c
===================================================================
--- branches/libgalago/push-presence/tests/test-bug-36.c	2006-06-13 02:59:33 UTC (rev 2845)
+++ branches/libgalago/push-presence/tests/test-bug-36.c	2006-06-13 06:11:06 UTC (rev 2846)
@@ -48,5 +48,7 @@
 
 	galago_uninit();
 
+	printf("Success. Bug 36 still closed.\n");
+
 	return 0;
 }



More information about the galago-commits mailing list