diff src/dbus-server.c @ 11146:1c5398ccbeb0

[gaim-migrate @ 13217] Gaim-DBUS signal export works with DBUS >= 0.35 Various gaim API functions available through DBUS committer: Tailor Script <tailor@pidgin.im>
author Piotr Zielinski <zielaj>
date Fri, 22 Jul 2005 19:47:29 +0000
parents f54740547c95
children ebb02ea3c789
line wrap: on
line diff
--- a/src/dbus-server.c	Fri Jul 22 07:11:08 2005 +0000
+++ b/src/dbus-server.c	Fri Jul 22 19:47:29 2005 +0000
@@ -21,7 +21,10 @@
  *
  */
 
+#define DBUS_API_SUBJECT_TO_CHANGE
+
 #include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
 #include <dbus/dbus-glib-bindings.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -36,12 +39,11 @@
 #include "conversation.h"
 #include "dbus-gaim.h"
 #include "dbus-server.h"
+#include "dbus-useful.h"
 #include "debug.h"
 #include "core.h"
 #include "value.h"
 
-static gint gaim_dbus_pointer_to_id(gpointer node);
-static gpointer gaim_dbus_id_to_pointer(gint id, GaimDBusPointerType type);
 
 
 /**************************************************************************/
@@ -51,9 +53,8 @@
 GType gaim_object_get_type(void);
 
 struct _GaimObject {
-	GObject parent;
-
-	int ping_signal_id;
+    GObject parent;
+    DBusGProxy *proxy;
 };
 
 typedef struct {
@@ -61,7 +62,6 @@
 } GaimObjectClass;
 
 
-
 #define GAIM_DBUS_TYPE_OBJECT              (gaim_object_get_type ())
 #define GAIM_DBUS_OBJECT(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GAIM_DBUS_TYPE_OBJECT, GaimObject))
 #define GAIM_DBUS_OBJECT_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GAIM_DBUS_TYPE_OBJECT, GaimObjectClass))
@@ -74,6 +74,15 @@
 GaimObject *gaim_dbus_object;
 static GQuark gaim_object_error_quark;
 
+#define NULLIFY(id) id = empty_to_null(id)
+
+static const char* empty_to_null(const char *str) {
+    if (str == NULL || str[0] == 0)
+	return NULL;
+    else
+	return str;
+}
+
 static const char* null_to_empty(const char *s) {
 	if (s)
 		return s;
@@ -87,517 +96,39 @@
 { 
 }
 
-
-
-/**************************************************************************/
-/** @name Signals                                                         */
-/**************************************************************************/
-
-/* used in #gaim_values_to_gvalues, undefined afterwards */
-#define my_arg(type) (ptr != NULL ? * ((type *)ptr) : va_arg(data, type))
-
-/**
-   Converts from a list of data into an GValue array.
-
-   @param gvalus      Array of empty gvalues to be filled.
-   @param number      The number of data items.
-   @param gaim_value  Array of #number pointers to GaimValues.  
-                      The types of of these GaimValues determine the type
-		      of data items.  The values do not matter.
-   @param mainptr     A pointer to a single data item.  If this pointer is not #NULL,
-                      then #number must be 1.
-   @param data        A va_list containing data items.  If 		      
-
-   Exactly one of #mainptr and #data must be not #NULL.  If #mainptr
-   is not #NULL, then there is a single piece of data at the address
-   pointed at by #mainptr.  If #data is not #NULL, then there are
-   #number data items in the #va_list #data.
- */
-static void gaim_values_to_gvalues(GValue *gvalue, int number,  
-		       GaimValue **gaim_values, gpointer mainptr, va_list data) 
-{
-	int i;
-	gpointer ptr;
-
-	g_assert(mainptr == NULL || data == NULL);
-	g_assert(mainptr != NULL || data != NULL);
-	g_assert(number == 1 || data != NULL);
-
-	for(i=0; i<number; i++, gvalue++) {
-		ptr = mainptr;
-		if (gaim_value_is_outgoing(gaim_values[i])) {
-			ptr = my_arg(gpointer);
-			g_assert(ptr);
-		}
-
-		switch(gaim_values[i]->type) {
-		case  GAIM_TYPE_CHAR:  	
-			g_value_init(gvalue, G_TYPE_CHAR);
-			g_value_set_char(gvalue, (char) my_arg(int));
-			break;
-		case  GAIM_TYPE_INT:  
-			g_value_init(gvalue, G_TYPE_INT);
-			g_value_set_int(gvalue, my_arg(gint));
-			break;
-		case  GAIM_TYPE_UINT:  
-			g_value_init(gvalue, G_TYPE_UINT);
-			g_value_set_uint(gvalue, my_arg(guint));
-			break;
-		case  GAIM_TYPE_BOOLEAN:  
-			g_value_init(gvalue, G_TYPE_BOOLEAN);
-			g_value_set_boolean(gvalue, my_arg(gboolean));
-			break;
-		case GAIM_TYPE_STRING: 
-			g_value_init(gvalue, G_TYPE_STRING);
-			g_value_set_string(gvalue, null_to_empty(my_arg(char*)));
-			break;
-		case GAIM_TYPE_SUBTYPE: /* registered pointers only! */
-			g_value_init(gvalue, G_TYPE_INT);
-			g_value_set_int(gvalue, 
-					gaim_dbus_pointer_to_id(my_arg(gpointer)));
-			break;
-		case GAIM_TYPE_POINTER:
- 		case GAIM_TYPE_OBJECT: 
-		case GAIM_TYPE_BOXED:
-			my_arg(gpointer); /* cannot pass general pointers */
-			g_value_init(gvalue, G_TYPE_INT);
-			g_value_set_int(gvalue, 0);
-			break;
-		
-		default:		/* no conversion implemented */
-			g_assert_not_reached();
-		}
-	}
-
-	if (data) 
-		va_end(data);
-}
-
-#undef my_arg			/* my_arg was only used in gaim_values_to_gvalues  */
-
-
-
-/**
-   Converts from GaimTypes to GTypes.
-
-   @param type   A GaimType to be converted.
-   @result       The result of the conversion (GType).
-*/
-static GType gaim_type_to_g_type(GaimType type)
+static void gaim_object_init(GaimObject *object) 
 {
-	switch(type) {
-	case  GAIM_TYPE_CHAR: 
-		return G_TYPE_CHAR;
-	case  GAIM_TYPE_INT:  
-		return G_TYPE_INT;
-	case  GAIM_TYPE_UINT:  
-		return G_TYPE_UINT;
-	case  GAIM_TYPE_BOOLEAN:  
-		return G_TYPE_BOOLEAN;
-	case GAIM_TYPE_STRING: 
-		return G_TYPE_STRING;
-	case GAIM_TYPE_SUBTYPE:    /* registered pointers only! */
-		return G_TYPE_INT;
-	case GAIM_TYPE_POINTER:
-	case GAIM_TYPE_BOXED:
- 	case GAIM_TYPE_OBJECT: 
-		return G_TYPE_INT; /* always 0 */
-	default:		   /* no conversion implemented */
-		g_assert_not_reached();
-	}	
-}
-
-
-static const char *gaim_dbus_convert_signal_name(const char *gaim_name) 
-{
-	int gaim_index, g_index;
-	char *g_name = g_new(char, strlen(gaim_name)+1);
-	gboolean capitalize_next = TRUE;
-
-	for(gaim_index = g_index = 0; gaim_name[gaim_index]; gaim_index++)
-		if (gaim_name[gaim_index] != '-' && gaim_name[gaim_index] != '_') {
-			if (capitalize_next)
-				g_name[g_index++] = g_ascii_toupper(gaim_name[gaim_index]);
-			else
-				g_name[g_index++] = gaim_name[gaim_index];
-			capitalize_next = FALSE;
-		} else
-			capitalize_next = TRUE;
-	g_name[g_index] = 0;
-	
-	return g_name;
-}
-
-/* Public signal-related functions */
-
-
-void gaim_dbus_invalid_marshaller(GClosure *closure,
-				  GValue *return_value,
-				  guint n_param_values,
-				  const GValue *param_values,
-				  gpointer invocation_hint,
-				  gpointer marshal_data)
-{
-	g_assert_not_reached();
-}
-
-int gaim_dbus_signal_register(GaimObject *object, const char *name, 
-			      GSignalCMarshaller marshaller,
-			      int num_values, ...) 
-{
-	va_list args;
-
-	va_start(args, num_values);
-
-	return g_signal_new_valist(name, G_OBJECT_TYPE(object),
-				   G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
-				   NULL, NULL, NULL, marshaller,
-				   G_TYPE_NONE, num_values, args);
-}
-
-void gaim_dbus_signal_emit(GaimObject *object, int dbus_id, ...) {
-	va_list args;
-	
-	va_start(args, dbus_id);
-	
-	gaim_dbus_signal_emit_valist(object, dbus_id, args);
-}
-
-void gaim_dbus_signal_emit_valist(GaimObject *object, int dbus_id, va_list args) {
-	g_signal_emit_valist(object, dbus_id, 0, args);
-}
-
-int gaim_dbus_signal_register_gaim(GaimObject *object, const char *name, 
-				   GSignalCMarshaller marshaller, 
-				   int num_values, GaimValue **values)
-{
-	int i;
-	int dbus_id;
-	GType *types;
-	
-	types = g_new0(GType, num_values);
-
-	for(i=0; i<num_values; i++) 
-		types[i] = gaim_type_to_g_type(values[i]->type);
-		
-	dbus_id = 
-		g_signal_newv(gaim_dbus_convert_signal_name(name),
-			      G_OBJECT_TYPE(object),
-			      G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
-			      NULL, NULL, NULL, marshaller,
-			      G_TYPE_NONE, num_values, types);
-
-	g_free(types);
-
-	return dbus_id;
-}
-
-
-void gaim_dbus_signal_emit_gaim(GaimObject *object, int dbus_id, int num_values, 
-				GaimValue **values, va_list vargs)
-{
-	GValue *args;
-	int i;
-
-	g_return_if_fail(dbus_id);
-
-	args = g_new0(GValue, num_values + 1);
-
-	g_value_init(args + 0, G_OBJECT_TYPE(object));
-	g_value_set_object(args + 0, object);
-
-	gaim_values_to_gvalues(args + 1, num_values, values, NULL, vargs);
-	
-	g_signal_emitv(args, dbus_id, 0, NULL);
-
-	for(i = 1; i <= num_values; i++)
-		g_value_unset(args + i);
-	
-	g_free(args);		
 }
 
-
-/**************************************************************************/
-/** @name Utility functions                                               */
-/**************************************************************************/
-
-#define error_unless_1(condition, str, parameter)		\
-	if (!(condition)) {					\
-		    g_set_error(error, gaim_object_error_quark,	\
-				DBUS_ERROR_NOT_FOUND,		\
-				str, parameter);		\
-		    return FALSE;				\
-	    }
-
-#define error_unless_2(condition, str, a,b)			\
-	if (!(condition)) {					\
-		    g_set_error(error, gaim_object_error_quark,	\
-				DBUS_ERROR_NOT_FOUND,		\
-				str, a,b);			\
-		    return FALSE;				\
-	    }
-
-typedef gboolean (*GaimNodeFilter)(GaimBlistNode *node, gpointer *user_data);
-
-static gboolean 
-filter_is_buddy(GaimBlistNode *node, gpointer *user_data) 
-{
-	return GAIM_BLIST_NODE_IS_BUDDY(node);
-}
-
-static gboolean 
-filter_is_online_buddy(GaimBlistNode *node, 
-		       gpointer *user_data) 
-{
-	return GAIM_BLIST_NODE_IS_BUDDY(node) && 
-	  GAIM_BUDDY_IS_ONLINE((GaimBuddy *)node);
-}
-
-
-static GList* 
-get_buddy_list (GList *created_list,		/**< can be NULL */
-		GaimBlistNode *gaim_buddy_list, /**< can be NULL */
-		GaimNodeFilter filter, 
-		gpointer user_data) 
-{
-	GaimBlistNode *node;
-
-	for(node = gaim_buddy_list; node; node = node->next) 
-	{
-		if ((*filter)(node, user_data)) 
-			created_list = g_list_prepend(created_list, node);
-
-		created_list = get_buddy_list(created_list, node->child,
-					      filter, user_data);
-	}
-	
-	return created_list;
-}
-
-
-
-/**************************************************************************/
-/** @name Implementations of remote DBUS calls                            */
-/**************************************************************************/
-
-static gboolean 
-gaim_object_ping(GaimObject *object, GError **error) 
-{
- 	gaim_dbus_signal_emit(object, object->ping_signal_id, "Ping Pong!"); 
-	return TRUE;
-}
-
-static gboolean 
-gaim_object_quit(GaimObject *obj, GError **error) 
-{
-	g_timeout_add(0, gaim_core_quit_cb, NULL);
-	return TRUE;
-}
-
-static gboolean
-gaim_object_connect_all(GaimObject *obj, GError **error)
-{
-	GList *cur;
-
-	for (cur = gaim_accounts_get_all(); cur != NULL; cur = cur->next) 
-		gaim_account_connect((GaimAccount*) cur->data);
-
-	return TRUE;
-}
-
-
-
-static gboolean
-gaim_object_get_buddy_list (GaimObject *obj, GArray **out_buddy_ids, 
-			    GError **error) 
-{
-	GList *node;
-	GList *buddy_list = get_buddy_list(NULL, gaim_get_blist()->root,
-					   &filter_is_buddy, NULL);
-	GArray *buddy_ids  = g_array_new(FALSE, TRUE, sizeof(gint32));;
-  	
-	buddy_list = g_list_reverse(buddy_list);
-
-	for (node = buddy_list; node; node = node->next) {
-		gint32 id = gaim_dbus_pointer_to_id(node->data);
-		g_array_append_val(buddy_ids, id);
-	}
-
-	g_list_free(buddy_list);
-	*out_buddy_ids = buddy_ids;
-
-	return TRUE;
-}
-
-
-
-
-
-static gboolean
-gaim_object_find_account(GaimObject *object, 
-			 const char *account_name, const char *protocol_name,
-			 gint *account_id, GError **error) 
-{
-	GaimAccount *account = gaim_accounts_find(account_name, protocol_name);
-	
-	error_unless_2(account, "Account '%s' with protocol '%s' not found", 
-			    account_name, protocol_name);
-
-	*account_id = gaim_dbus_pointer_to_id(account);
-	return TRUE;
-}
-
-static gboolean
-gaim_object_find_buddy(GaimObject *object, gint account_id, const char *buddy_name,
-		       gint *buddy_id, GError **error)
-{
-	GaimAccount *account;
-	GaimBuddy *buddy;
-
-	account = gaim_dbus_id_to_pointer(account_id, DBUS_POINTER_ACCOUNT);
-	error_unless_1(account, "Invalid account id: %i", account_id);	
-
-	buddy = gaim_find_buddy(account, buddy_name);
-	error_unless_1(account, "Buddy '%s' not found.", buddy_name);	
-
-	*buddy_id = gaim_dbus_pointer_to_id(buddy);
-	return TRUE;
-}
-
-static gboolean
-gaim_object_start_im_conversation (GaimObject *object, gint buddy_id, GError **error)
-{
-	GaimBuddy *buddy = (GaimBuddy*) gaim_dbus_id_to_pointer(buddy_id, 
-								DBUS_POINTER_BUDDY);
-	
-	error_unless_1(buddy, "Invalid buddy id: %i", buddy_id);
-
-	gaim_conversation_new(GAIM_CONV_IM, buddy->account, buddy->name);
-
-	return TRUE;
-}
-
-
-
-/**************************************************************************/
-/** @name Gaim DBUS property handling functions                           */
-/**************************************************************************/
-
-
-typedef struct _GaimDBusProperty {
-	char *name;
-	gint offset;
-	GaimType type;
-} GaimDBusProperty;
-
-/* change GAIM_TYPE into G_TYPE */
-	  
-static gboolean
-gaim_dbus_get_property(GaimDBusProperty *list, int list_len, 
-		       gpointer data, const char *name, 
-		       GValue *value, GError **error)
-{
-	int i;
-
-	for(i=0; i<list_len; i++) {
-		if (!strcmp(list[i].name, name)) {
-			gpointer ptr;
-			GaimValue gaim_value, *gaim_value_ptr;
-
-			ptr = G_STRUCT_MEMBER_P(data, list[i].offset);
-			gaim_value.type = list[i].type;
-			gaim_value.flags = 0;
-			gaim_value_ptr = &gaim_value;
-			
-			gaim_values_to_gvalues(value, 1, &gaim_value_ptr, 
-					       ptr, NULL);
-			return TRUE;
-		}
-	}
-
-	g_value_init(value, G_TYPE_INT);
-	g_value_set_int(value, 0);
-	error_unless_1(FALSE, "Invalid property '%s'", name);	
-}
-
-
-#define DECLARE_PROPERTY(maintype, name, type) {#name, G_STRUCT_OFFSET(maintype, name), type}
-
-GaimDBusProperty buddy_properties [] = {
-	DECLARE_PROPERTY(GaimBuddy, name, GAIM_TYPE_STRING),
-	DECLARE_PROPERTY(GaimBuddy, alias, GAIM_TYPE_STRING),
-	DECLARE_PROPERTY(GaimBuddy, server_alias, GAIM_TYPE_STRING),
-	DECLARE_PROPERTY(GaimBuddy, account, GAIM_TYPE_SUBTYPE) 
-};
-
-GaimDBusProperty account_properties [] = {
-	DECLARE_PROPERTY(GaimAccount, username, GAIM_TYPE_STRING),
-	DECLARE_PROPERTY(GaimAccount, alias, GAIM_TYPE_STRING),
-	DECLARE_PROPERTY(GaimAccount, user_info, GAIM_TYPE_STRING),
-	DECLARE_PROPERTY(GaimAccount, protocol_id, GAIM_TYPE_STRING),
-};
-
-GaimDBusProperty contact_properties [] = {
-	DECLARE_PROPERTY(GaimContact, alias, GAIM_TYPE_STRING),
-	DECLARE_PROPERTY(GaimContact, totalsize, GAIM_TYPE_INT),
-	DECLARE_PROPERTY(GaimContact, currentsize, GAIM_TYPE_INT),
-	DECLARE_PROPERTY(GaimContact, online, GAIM_TYPE_INT),
-	DECLARE_PROPERTY(GaimContact, priority, GAIM_TYPE_SUBTYPE),
-	DECLARE_PROPERTY(GaimContact, priority_valid, GAIM_TYPE_BOOLEAN),
-};
-
-GaimDBusProperty group_properties [] = {
-	DECLARE_PROPERTY(GaimGroup, name, GAIM_TYPE_STRING),
-	DECLARE_PROPERTY(GaimGroup, totalsize, GAIM_TYPE_INT),
-	DECLARE_PROPERTY(GaimGroup, currentsize, GAIM_TYPE_INT),
-	DECLARE_PROPERTY(GaimGroup, online, GAIM_TYPE_INT),
-};
-
-GaimDBusProperty chat_properties [] = {
-	DECLARE_PROPERTY(GaimChat, alias, GAIM_TYPE_STRING),
-	DECLARE_PROPERTY(GaimChat, account, GAIM_TYPE_SUBTYPE),
-};
-
-
-#define DECLARE_PROPERTY_HANDLER(type, gaim_type)			\
-	static gboolean							\
-	gaim_object_get_##type##_property (GaimObject *object,		\
-					   gint id, const char *property_name, \
-					   GValue *value, GError **error) \
-	{								\
-		gpointer ptr = gaim_dbus_id_to_pointer(id, gaim_type); \
-									\
-		error_unless_1(ptr, "Invalid " #type " id: %i", id);	\
-									\
-		return gaim_dbus_get_property(type##_properties,	\
-					      G_N_ELEMENTS(type##_properties), \
-					      ptr, property_name, value, error); \
-	}
-
-DECLARE_PROPERTY_HANDLER(buddy, DBUS_POINTER_BUDDY)
-DECLARE_PROPERTY_HANDLER(account, DBUS_POINTER_ACCOUNT)
-DECLARE_PROPERTY_HANDLER(contact, DBUS_POINTER_CONTACT)
-DECLARE_PROPERTY_HANDLER(group, DBUS_POINTER_GROUP)
-DECLARE_PROPERTY_HANDLER(chat, DBUS_POINTER_CHAT)
-
-#include "dbus-server-bindings.c"
-
-
-
 /**************************************************************************/
 /** @name Gaim DBUS pointer registration mechanism                        */
 /**************************************************************************/
 
+GaimDBusPointerType dbus_type_parent[DBUS_POINTER_LASTTYPE];
+
 static GHashTable *map_id_node; 
 static GHashTable *map_id_type; 
 static GHashTable *map_node_id; 
 
+
+#define DECLARE_TYPE(type, parent) \
+	dbus_type_parent[DBUS_POINTER_##type] = DBUS_POINTER_##parent
+
 void gaim_dbus_init_ids(void) {
-
+	int i;
 
 	map_id_node = g_hash_table_new (g_direct_hash, g_direct_equal);
 	map_id_type = g_hash_table_new (g_direct_hash, g_direct_equal);
 	map_node_id = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+	for (i = 0; i < DBUS_POINTER_LASTTYPE; i++)
+		dbus_type_parent[i] = DBUS_POINTER_NONE;
+
+	/* some manual corrections */
+	DECLARE_TYPE(GaimBuddy, GaimBlistNode);
+	DECLARE_TYPE(GaimContact, GaimBlistNode);
+	DECLARE_TYPE(GaimChat, GaimBlistNode);
+	DECLARE_TYPE(GaimGroup, GaimBlistNode);
 }
 
 void gaim_dbus_register_pointer(gpointer node, GaimDBusPointerType type) 
@@ -625,20 +156,221 @@
 }
 
 static gint gaim_dbus_pointer_to_id(gpointer node) {
-	g_assert(map_node_id);
-
 	gint id = GPOINTER_TO_INT(g_hash_table_lookup(map_node_id, node));
 	g_return_val_if_fail(id, 0);
 	return id;
 }
 	
 static gpointer gaim_dbus_id_to_pointer(gint id, GaimDBusPointerType type) {
-	if (type != GPOINTER_TO_INT(g_hash_table_lookup(map_id_type, 
-							GINT_TO_POINTER(id))))
+	GaimDBusPointerType objtype = 
+		GPOINTER_TO_INT(g_hash_table_lookup(map_id_type, 
+						    GINT_TO_POINTER(id)));
+							    
+	while (objtype != type && objtype != DBUS_POINTER_NONE)
+		objtype = dbus_type_parent[objtype];
+
+	if (objtype == type)
+		return g_hash_table_lookup(map_id_node, GINT_TO_POINTER(id));
+	else
 		return NULL;
-	return g_hash_table_lookup(map_id_node, GINT_TO_POINTER(id));
 }
 	
+/**************************************************************************/
+/** @name Useful functions                                                */
+/**************************************************************************/
+
+
+#define error_unless_1(condition, str, parameter)		\
+	if (!(condition)) {					\
+		    g_set_error(error, gaim_object_error_quark,	\
+				DBUS_ERROR_NOT_FOUND,		\
+				str, parameter);		\
+		    return FALSE;				\
+	    }
+
+#define error_unless_2(condition, str, a,b)			\
+	if (!(condition)) {					\
+		    g_set_error(error, gaim_object_error_quark,	\
+				DBUS_ERROR_NOT_FOUND,		\
+				str, a,b);			\
+		    return FALSE;				\
+	    }
+
+#define GAIM_DBUS_ID_TO_POINTER(ptr, id, type)				\
+	G_STMT_START {							\
+		ptr = ((type*) gaim_dbus_id_to_pointer			\
+		       (id, DBUS_POINTER_##type));			\
+		error_unless_2(ptr != NULL || id == 0,			\
+			       "%s object with ID = %i not found",	\
+			       #type, id);				\
+	} G_STMT_END
+	       
+
+#define GAIM_DBUS_POINTER_TO_ID(id, ptr)				\
+	G_STMT_START {							\
+		gpointer _ptr = ptr;					\
+		id = gaim_dbus_pointer_to_id(_ptr);			\
+		error_unless_1(ptr == NULL || id != 0,			\
+			       "Result object not registered (%i)",	\
+			       id);					\
+	} G_STMT_END
+
+
+/**************************************************************************/
+/** @name Signals                                                         */
+/**************************************************************************/
+
+
+
+static  char *gaim_dbus_convert_signal_name(const char *gaim_name) 
+{
+	int gaim_index, g_index;
+	char *g_name = g_new(char, strlen(gaim_name)+1);
+	gboolean capitalize_next = TRUE;
+
+	for(gaim_index = g_index = 0; gaim_name[gaim_index]; gaim_index++)
+		if (gaim_name[gaim_index] != '-' && gaim_name[gaim_index] != '_') {
+			if (capitalize_next)
+				g_name[g_index++] = g_ascii_toupper(gaim_name[gaim_index]);
+			else
+				g_name[g_index++] = gaim_name[gaim_index];
+			capitalize_next = FALSE;
+		} else
+			capitalize_next = TRUE;
+	g_name[g_index] = 0;
+	
+	return g_name;
+}
+
+#define my_arg(type) (ptr != NULL ? * ((type *)ptr) : va_arg(data, type))
+
+static void gaim_dbus_message_append_gaim_values(DBusMessageIter *iter,
+						 int number,
+						 GaimValue **gaim_values, 
+						 va_list data) 
+{
+    int i;
+
+    for(i=0; i<number; i++) {
+	const char *str;
+	int id;
+	gint xint;
+	guint xuint;
+	gboolean xboolean;
+	gpointer ptr = NULL;
+	if (gaim_value_is_outgoing(gaim_values[i])) {
+	    ptr = my_arg(gpointer);
+	    g_assert(ptr);
+	}
+	
+	switch(gaim_values[i]->type) {
+	case  GAIM_TYPE_INT:  
+	    g_print("appending int\n");
+	    xint = my_arg(gint);
+	    dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &xint);
+	    break;
+	case  GAIM_TYPE_UINT:  
+	    xuint = my_arg(guint);
+	    g_print("appending uint\n");
+	    dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &xuint);
+	    break;
+	case  GAIM_TYPE_BOOLEAN:  
+	    g_print("appending boolean\n");
+	    xboolean = my_arg(gboolean);
+	    dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &xboolean);
+	    break;
+	case GAIM_TYPE_STRING: 
+	    g_print("appending string\n");
+	    str = null_to_empty(my_arg(char*));
+	    dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &str);
+	    break;
+	case GAIM_TYPE_SUBTYPE: /* registered pointers only! */
+	case GAIM_TYPE_POINTER:
+	case GAIM_TYPE_OBJECT: 
+	case GAIM_TYPE_BOXED:		
+	    g_print("appending obj\n");
+	    id = gaim_dbus_pointer_to_id(my_arg(gpointer));
+	    dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &id);
+	    break;
+	default:		/* no conversion implemented */
+	    g_assert_not_reached();
+	}
+    }
+}
+
+#undef my_arg
+
+void gaim_dbus_signal_emit_gaim(GaimObject *object, char *name, int num_values, 
+				GaimValue **values, va_list vargs)
+{
+	/* pass name */
+    DBusMessage *signal;
+    DBusMessageIter iter;
+    char *newname;
+
+    g_print("Emitting %s\n", name);    
+    g_return_if_fail(object->proxy);
+    
+    newname =  gaim_dbus_convert_signal_name(name);
+    signal = dbus_message_new_signal(DBUS_PATH_GAIM, DBUS_INTERFACE_GAIM, newname);
+    dbus_message_iter_init_append(signal, &iter);
+
+    gaim_dbus_message_append_gaim_values(&iter, num_values, values, vargs);
+
+    dbus_g_proxy_send(object->proxy, signal, NULL);
+
+    g_free(newname);
+    dbus_message_unref(signal);
+}
+
+
+/**************************************************************/
+/* DBus bindings ...                                          */
+/**************************************************************/
+
+
+
+GArray* gaim_dbusify_GList(GList *list, gboolean free_memory) {
+	GArray *array;
+	GList *elem;
+
+	array = g_array_new (FALSE, TRUE, sizeof (guint32));
+	for(elem = list; elem != NULL; elem = elem->next) {
+		int objectid;
+
+		objectid = gaim_dbus_pointer_to_id(elem->data);
+		g_array_append_val(array, objectid);
+	}
+
+	if (free_memory)
+		g_list_free(list);
+
+	return array;
+}
+
+GArray* gaim_dbusify_GSList(GSList *list, gboolean free_memory) {
+	GArray *array;
+	GSList *elem;
+
+	array = g_array_new (FALSE, TRUE, sizeof (guint32));
+	for(elem = list; elem != NULL; elem = elem->next) {
+		int objectid;
+
+		objectid = gaim_dbus_pointer_to_id(elem->data);
+		g_array_append_val(array, objectid);
+	}
+
+	if (free_memory)
+		g_slist_free(list);
+	return array;
+}
+
+#include "dbus-generated-code.c"
+
+#include "dbus-server-bindings.c"
+
+
+
 
 
 /**************************************************************************/
@@ -646,6 +378,8 @@
 /**************************************************************************/
 
 
+/* fixme: why do we need two functions here instead of one?  */
+
 gboolean gaim_dbus_connect(GaimObject *object) 
 {
 	DBusGConnection *connection;
@@ -653,10 +387,10 @@
 	DBusGProxy *driver_proxy;
 	guint32 request_name_ret;
 
-
 	gaim_debug_misc("dbus", "launching dbus server\n");
 					
-	/* Connect to the bus */
+	dbus_g_object_type_install_info (GAIM_DBUS_TYPE_OBJECT,
+					 &dbus_glib_gaim_object_object_info);	/* Connect to the bus */
 
 	error = NULL;
 	connection = dbus_g_bus_get(DBUS_BUS_STARTER, &error);
@@ -674,13 +408,6 @@
 
 
 
-	dbus_g_object_type_install_info (GAIM_DBUS_TYPE_OBJECT,
-					 &dbus_glib_gaim_object_object_info);
-
-	dbus_g_connection_register_g_object (connection, DBUS_PATH_GAIM,
-					     (GObject*) object);
-
-
 	/* Obtain a proxy for the DBus object  */
 
 	driver_proxy = dbus_g_proxy_new_for_name (connection,
@@ -710,29 +437,37 @@
 
 	gaim_debug_misc ("dbus", "GLib test service has name '%s'\n", 
 			 DBUS_SERVICE_GAIM);
+
+
+
+	dbus_g_connection_register_g_object (connection, DBUS_PATH_GAIM,
+					     (GObject*) object);
+
+	object->proxy = dbus_g_proxy_new_for_name (connection,
+						  DBUS_SERVICE_GAIM,
+						  DBUS_PATH_GAIM,
+						  DBUS_INTERFACE_GAIM);
+
 	gaim_debug_misc ("dbus", "GLib test service entering main loop\n");
 
 	return TRUE;
 }
 
 
-static void gaim_object_init(GaimObject *object) 
-{
-
-	object->ping_signal_id =
-		gaim_dbus_signal_register(object, "PingSignal", 
-					  g_cclosure_marshal_VOID__STRING,
-					  1, G_TYPE_STRING);
-}
 
 
 gboolean gaim_dbus_init(void) 
 {
-	gaim_dbus_init_ids();
-	gaim_object_error_quark =
-		g_quark_from_static_string("org.gaim.GaimError");
+    gaim_dbus_init_ids();
+    gaim_object_error_quark =
+	g_quark_from_static_string("org.gaim.GaimError");
+
+
 
 	gaim_dbus_object = GAIM_DBUS_OBJECT(g_object_new (GAIM_DBUS_TYPE_OBJECT, NULL));
 
+	gaim_dbus_object->proxy = NULL;
 	return TRUE;
 }
+
+